Saving also userAccountId and bankAccountId on child entities

This commit is contained in:
dankito 2024-08-28 01:39:25 +02:00
parent d356d45db7
commit 4856ced158
10 changed files with 118 additions and 81 deletions

View File

@ -1,6 +1,5 @@
package net.codinux.banking.dataaccess 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.UserAccount
import net.codinux.banking.dataaccess.entities.AccountTransactionEntity import net.codinux.banking.dataaccess.entities.AccountTransactionEntity
import net.codinux.banking.dataaccess.entities.UserAccountEntity import net.codinux.banking.dataaccess.entities.UserAccountEntity
@ -10,13 +9,11 @@ interface BankingRepository {
fun getAllUserAccounts(): List<UserAccountEntity> fun getAllUserAccounts(): List<UserAccountEntity>
suspend fun persistUserAccount(userAccount: UserAccount): Long suspend fun persistUserAccount(userAccount: UserAccount): UserAccountEntity
fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel> fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel>
fun getAllAccountTransactions(): List<AccountTransactionEntity> fun getAllAccountTransactions(): List<AccountTransactionEntity>
suspend fun persistAccountTransactions(transactions: Collection<AccountTransaction>): Map<Long, AccountTransaction>
} }

View File

@ -20,36 +20,31 @@ class InMemoryBankingRepository(
override fun getAllUserAccounts(): List<UserAccountEntity> = userAccounts.toList() override fun getAllUserAccounts(): List<UserAccountEntity> = userAccounts.toList()
override suspend fun persistUserAccount(userAccount: UserAccount): Long { override suspend fun persistUserAccount(userAccount: UserAccount): UserAccountEntity {
val entity = map(userAccount) val entity = map(userAccount) // TODO: may fix someday and add also BankAccounts and their id
this.userAccounts.add(entity) this.userAccounts.add(entity)
return entity.id return entity
} }
override fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel> = override fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel> =
transactions.map { AccountTransactionViewModel(it.id, it) } transactions.map { AccountTransactionViewModel(it) }
override fun getAllAccountTransactions(): List<AccountTransactionEntity> = transactions.toList() override fun getAllAccountTransactions(): List<AccountTransactionEntity> = transactions.toList()
override suspend fun persistAccountTransactions(transactions: Collection<AccountTransaction>): Map<Long, AccountTransaction> {
val entities = transactions.map { map(it) }
this.transactions.addAll(entities)
return entities.associateBy { it.id }
}
private fun map(account: UserAccount) = UserAccountEntity( private fun map(account: UserAccount) = UserAccountEntity(
nextId++, nextId++,
account.bankCode, account.loginName, account.password, account.bankName, account.bic, account.customerName, account.userId, 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(), emptyList(), account.selectedTanMethodId, emptyList(), account.selectedTanMediumName, emptyList(),
account.bankingGroup, account.iconUrl, account.wrongCredentialsEntered, account.userSetDisplayName, account.displayIndex account.bankingGroup, account.iconUrl, account.wrongCredentialsEntered, account.userSetDisplayName, account.displayIndex
) )
private fun map(transaction: AccountTransaction) = AccountTransactionEntity( // TODO: someday may fix and get userAccountId and bankAccountId
private fun map(transaction: AccountTransaction, userAccountId: Long = nextId++, bankAccountId: Long = nextId++) = AccountTransactionEntity(
nextId++, nextId++,
userAccountId, bankAccountId,
transaction.amount, transaction.currency, transaction.reference, transaction.amount, transaction.currency, transaction.reference,
transaction.bookingDate, transaction.valueDate, transaction.bookingDate, transaction.valueDate,
transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId, transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId,

View File

@ -11,7 +11,7 @@ import kotlin.enums.EnumEntries
import kotlin.js.JsName import kotlin.js.JsName
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
class SqliteBankingRepository( open class SqliteBankingRepository(
sqlDriver: SqlDriver sqlDriver: SqlDriver
) : BankingRepository { ) : BankingRepository {
@ -31,7 +31,7 @@ class SqliteBankingRepository(
}.executeAsList() }.executeAsList()
} }
override suspend fun persistUserAccount(userAccount: UserAccount): Long { override suspend fun persistUserAccount(userAccount: UserAccount): UserAccountEntity {
return userAccountQueries.transactionWithResult { return userAccountQueries.transactionWithResult {
userAccountQueries.insertUserAccount(userAccount.bankCode, userAccount.loginName, userAccount.password, userAccount.bankName, userAccount.bic, userAccountQueries.insertUserAccount(userAccount.bankCode, userAccount.loginName, userAccount.password, userAccount.bankName, userAccount.bic,
userAccount.customerName, userAccount.userId, userAccount.selectedTanMethodId, userAccount.selectedTanMediumName, userAccount.customerName, userAccount.userId, userAccount.selectedTanMethodId, userAccount.selectedTanMediumName,
@ -40,9 +40,9 @@ class SqliteBankingRepository(
val userAccountId = getLastInsertedId() // getLastInsertedId() / last_insert_rowid() has to be called in a transaction with the insert operation, otherwise it will not work val userAccountId = getLastInsertedId() // getLastInsertedId() / last_insert_rowid() has to be called in a transaction with the insert operation, otherwise it will not work
persistBankAccounts(userAccountId, userAccount.accounts) val bankAccounts = persistBankAccounts(userAccountId, userAccount.accounts)
userAccountId UserAccountEntity(userAccountId, userAccount, bankAccounts)
} }
} }
@ -58,18 +58,20 @@ class SqliteBankingRepository(
mapToAmount(balance), mapToDate(retrievedTransactionsFrom), mapToDate(retrievedTransactionsTo), mapToAmount(balance), mapToDate(retrievedTransactionsFrom), mapToDate(retrievedTransactionsTo),
mapToInt(countDaysForWhichTransactionsAreKept), mapToInt(countDaysForWhichTransactionsAreKept),
mutableListOf(), mutableListOf(),
userSetDisplayName, mapToInt(displayIndex), userSetDisplayName, mapToInt(displayIndex),
hideAccount, includeInAutomaticAccountsUpdate hideAccount, includeInAutomaticAccountsUpdate
) )
}.executeAsList() }.executeAsList()
private suspend fun persistBankAccounts(userAccountId: Long, bankAccounts: Collection<BankAccount>): Map<Long, BankAccount> = private suspend fun persistBankAccounts(userAccountId: Long, bankAccounts: Collection<BankAccount>): List<BankAccountEntity> =
bankAccounts.associate { persistBankAccount(userAccountId, it) } bankAccounts.map { persistBankAccount(userAccountId, it) }
/** /**
* Has to be executed in a transaction in order that getting persisted BankAccount's id works~ * Has to be executed in a transaction in order that getting persisted BankAccount's id works~
*/ */
private suspend fun persistBankAccount(userAccountId: Long, account: BankAccount): Pair<Long, BankAccount> { private suspend fun persistBankAccount(userAccountId: Long, account: BankAccount): BankAccountEntity {
userAccountQueries.insertBankAccount( userAccountQueries.insertBankAccount(
userAccountId, userAccountId,
account.identifier, account.accountHolderName, mapEnum(account.type), account.identifier, account.accountHolderName, mapEnum(account.type),
@ -86,19 +88,27 @@ class SqliteBankingRepository(
account.hideAccount, account.includeInAutomaticAccountsUpdate account.hideAccount, account.includeInAutomaticAccountsUpdate
) )
return Pair(getLastInsertedId(), account) val accountId = getLastInsertedId()
val accountTransactionEntities = account.bookedTransactions.map { transaction ->
persistTransaction(userAccountId, accountId, transaction)
}
return BankAccountEntity(accountId, userAccountId, account, accountTransactionEntities)
} }
override fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel> = override fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel> =
accountTransactionQueries.selectAllTransactionsAsViewModel { id, amount, currency, reference, valueDate, otherPartyName, bookingText, sepaReference, userSetDisplayName, category -> accountTransactionQueries.selectAllTransactionsAsViewModel { id, userAccountId, bankAccountId, amount, currency, reference, valueDate, otherPartyName, bookingText, sepaReference, userSetDisplayName, category ->
AccountTransactionViewModel(id, mapToAmount(amount), currency, sepaReference ?: reference, mapToDate(valueDate), otherPartyName, bookingText, userSetDisplayName, category) AccountTransactionViewModel(id, userAccountId, bankAccountId, mapToAmount(amount), currency, sepaReference ?: reference, mapToDate(valueDate), otherPartyName, bookingText, userSetDisplayName, category)
}.executeAsList() }.executeAsList()
override fun getAllAccountTransactions(): List<AccountTransactionEntity> { override fun getAllAccountTransactions(): List<AccountTransactionEntity> {
return accountTransactionQueries.selectAllTransactions { id, amount, currency, reference, bookingDate, valueDate, otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, 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 -> return accountTransactionQueries.selectAllTransactions { id, userAccountId, bankAccountId, amount, currency, reference, bookingDate, valueDate, otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, 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 ->
AccountTransactionEntity( AccountTransactionEntity(
id, id,
userAccountId, bankAccountId,
Amount(amount), currency, reference, Amount(amount), currency, reference,
mapToDate(bookingDate), mapToDate(valueDate), mapToDate(bookingDate), mapToDate(valueDate),
otherPartyName, otherPartyBankCode, otherPartyAccountId, otherPartyName, otherPartyBankCode, otherPartyAccountId,
@ -128,18 +138,13 @@ class SqliteBankingRepository(
}.executeAsList() }.executeAsList()
} }
override suspend fun persistAccountTransactions(transactions: Collection<AccountTransaction>): Map<Long, AccountTransaction> =
accountTransactionQueries.transactionWithResult {
transactions.associate {
saveAccountTransaction(it)
}
}
/** /**
* Has to be executed in a transaction in order that getting persisted BankAccount's id works~ * Has to be executed in a transaction in order that getting persisted BankAccount's id works~
*/ */
private suspend fun saveAccountTransaction(transaction: AccountTransaction): Pair<Long, AccountTransaction> { protected open suspend fun persistTransaction(userAccountId: Long, bankAccountId: Long, transaction: AccountTransaction): AccountTransactionEntity {
accountTransactionQueries.insertTransaction( accountTransactionQueries.insertTransaction(
userAccountId, bankAccountId,
mapAmount(transaction.amount), transaction.currency, transaction.reference, mapAmount(transaction.amount), transaction.currency, transaction.reference,
mapDate(transaction.bookingDate), mapDate(transaction.valueDate), mapDate(transaction.bookingDate), mapDate(transaction.valueDate),
transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId, transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId,
@ -165,7 +170,7 @@ class SqliteBankingRepository(
transaction.transactionReferenceNumber, transaction.relatedReferenceNumber transaction.transactionReferenceNumber, transaction.relatedReferenceNumber
) )
return Pair(getLastInsertedId(), transaction) return AccountTransactionEntity(getLastInsertedId(), userAccountId, bankAccountId, transaction)
} }

View File

@ -6,6 +6,8 @@ import net.codinux.banking.client.model.Amount
class AccountTransactionEntity( class AccountTransactionEntity(
val id: Long, val id: Long,
val userAccountId: Long,
val bankAccountId: Long,
amount: Amount, amount: Amount,
currency: String, currency: String,
@ -78,4 +80,28 @@ class AccountTransactionEntity(
transactionReferenceNumber, relatedReferenceNumber, transactionReferenceNumber, relatedReferenceNumber,
userSetDisplayName, category, notes userSetDisplayName, category, notes
) ) {
constructor(id: Long, userAccountId: Long, bankAccountId: Long, transaction: AccountTransaction) : this(
id, userAccountId, bankAccountId,
transaction.amount, transaction.currency, transaction.reference, transaction.bookingDate, transaction.valueDate,
transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId, transaction.bookingText,
transaction.userSetDisplayName, transaction.category, transaction.notes, transaction.information,
transaction.statementNumber, transaction.sequenceNumber,
transaction.openingBalance, 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.currencyType, transaction.bookingKey,
transaction.referenceForTheAccountOwner, transaction.referenceOfTheAccountServicingInstitution,
transaction.supplementaryDetails,
transaction.transactionReferenceNumber, transaction.relatedReferenceNumber
)
}

View File

@ -25,8 +25,8 @@ class BankAccountEntity(
countDaysForWhichTransactionsAreKept: Int? = null, countDaysForWhichTransactionsAreKept: Int? = null,
// bookedTransactions: MutableList<AccountTransaction> = mutableListOf(), bookedTransactions: MutableList<AccountTransactionEntity> = mutableListOf(),
// unbookedTransactions: MutableList<UnbookedAccountTransaction> = mutableListOf(), unbookedTransactions: MutableList<UnbookedAccountTransaction> = mutableListOf(),
userSetDisplayName: String? = null, userSetDisplayName: String? = null,
displayIndex: Int = 0, displayIndex: Int = 0,
@ -37,6 +37,19 @@ class BankAccountEntity(
identifier, accountHolderName, type, iban, subAccountNumber, productName, currency, accountLimit, identifier, accountHolderName, type, iban, subAccountNumber, productName, currency, accountLimit,
isAccountTypeSupportedByApplication, features, balance, isAccountTypeSupportedByApplication, features, balance,
retrievedTransactionsFrom, retrievedTransactionsTo, false, countDaysForWhichTransactionsAreKept, retrievedTransactionsFrom, retrievedTransactionsTo, false, countDaysForWhichTransactionsAreKept,
mutableListOf(), mutableListOf(), bookedTransactions as MutableList<AccountTransaction>, unbookedTransactions,
userSetDisplayName, displayIndex, hideAccount, includeInAutomaticAccountsUpdate userSetDisplayName, displayIndex, hideAccount, includeInAutomaticAccountsUpdate
) ) {
constructor(id: Long, userAccountId: Long, account: BankAccount, transactions: List<AccountTransactionEntity> = emptyList()) : this(
id, userAccountId,
account.identifier, account.accountHolderName, account.type, account.iban, account.subAccountNumber,
account.productName, account.currency, account.accountLimit,
account.isAccountTypeSupportedByApplication, account.features, account.balance,
account.retrievedTransactionsFrom, account.retrievedTransactionsTo, account.countDaysForWhichTransactionsAreKept,
transactions.toMutableList(), mutableListOf(),
account.userSetDisplayName, account.displayIndex, account.hideAccount, account.includeInAutomaticAccountsUpdate
)
val bookedTransactionsEntities: MutableList<AccountTransactionEntity> = bookedTransactions
}

View File

@ -18,7 +18,7 @@ class UserAccountEntity(
customerName: String, customerName: String,
userId: String = loginName, userId: String = loginName,
accounts: List<BankAccountEntity> = emptyList(), // TODO: make accounts open override val accounts: List<BankAccountEntity> = emptyList(),
selectedTanMethodId: String? = null, selectedTanMethodId: String? = null,
tanMethods: List<TanMethod> = listOf(), tanMethods: List<TanMethod> = listOf(),
@ -42,14 +42,12 @@ class UserAccountEntity(
} }
constructor(id: Long, user: UserAccount) : this( constructor(id: Long, user: UserAccount, bankAccounts: List<BankAccountEntity>) : this(
id, id,
user.bankCode, user.loginName, user.password, user.bankName, user.bic, user.customerName, user.userId, user.bankCode, user.loginName, user.password, user.bankName, user.bic, user.customerName, user.userId,
emptyList(), user.selectedTanMethodId, emptyList(), user.selectedTanMediumName, emptyList(), bankAccounts,
user.selectedTanMethodId, emptyList(), user.selectedTanMediumName, emptyList(),
user.bankingGroup, user.iconUrl, user.wrongCredentialsEntered, user.userSetDisplayName, user.displayIndex user.bankingGroup, user.iconUrl, user.wrongCredentialsEntered, user.userSetDisplayName, user.displayIndex
) )
val accountEntities: List<BankAccountEntity> = accounts
} }

View File

@ -3,9 +3,12 @@ package net.codinux.banking.ui.model
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
import net.codinux.banking.client.model.AccountTransaction import net.codinux.banking.client.model.AccountTransaction
import net.codinux.banking.client.model.Amount import net.codinux.banking.client.model.Amount
import net.codinux.banking.dataaccess.entities.AccountTransactionEntity
data class AccountTransactionViewModel( data class AccountTransactionViewModel(
val id: Long, val id: Long,
val userAccountId: Long,
val bankAccountId: Long,
val amount: Amount, val amount: Amount,
val currency: String, val currency: String,
@ -17,6 +20,8 @@ data class AccountTransactionViewModel(
val userSetDisplayName: String? = null, val userSetDisplayName: String? = null,
val category: String? = null val category: String? = null
) { ) {
constructor(id: Long, transaction: AccountTransaction) constructor(entity: AccountTransactionEntity) : this(entity.id, entity.userAccountId, entity.bankAccountId, entity)
: this(id, transaction.amount, transaction.currency, transaction.reference, transaction.valueDate, transaction.otherPartyName, transaction.bookingText)
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)
} }

View File

@ -7,11 +7,12 @@ import net.codinux.banking.client.fints4k.FinTs4kBankingClient
import net.codinux.banking.client.model.AccountTransaction import net.codinux.banking.client.model.AccountTransaction
import net.codinux.banking.client.model.Amount import net.codinux.banking.client.model.Amount
import net.codinux.banking.client.model.options.GetAccountDataOptions import net.codinux.banking.client.model.options.GetAccountDataOptions
import net.codinux.banking.client.model.options.RetrieveTransactions
import net.codinux.banking.client.model.request.GetAccountDataRequest import net.codinux.banking.client.model.request.GetAccountDataRequest
import net.codinux.banking.client.model.response.* import net.codinux.banking.client.model.response.ErrorType
import net.codinux.banking.client.model.response.GetAccountDataResponse
import net.codinux.banking.client.model.response.Response
import net.codinux.banking.client.model.response.ResponseType
import net.codinux.banking.dataaccess.BankingRepository import net.codinux.banking.dataaccess.BankingRepository
import net.codinux.banking.dataaccess.entities.UserAccountEntity
import net.codinux.banking.fints.config.FinTsClientConfiguration import net.codinux.banking.fints.config.FinTsClientConfiguration
import net.codinux.banking.fints.config.FinTsClientOptions import net.codinux.banking.fints.config.FinTsClientOptions
import net.codinux.banking.ui.model.AccountTransactionViewModel import net.codinux.banking.ui.model.AccountTransactionViewModel
@ -73,28 +74,19 @@ class BankingService(
} }
private suspend fun handleSuccessfulGetAccountDataResponse(response: GetAccountDataResponse) { private suspend fun handleSuccessfulGetAccountDataResponse(response: GetAccountDataResponse) {
try {
val newTransactions = response.bookedTransactions
val createdIds = bankingRepository.persistAccountTransactions(newTransactions)
log.info { "Saved ${newTransactions.size} transactions" }
val transactions = uiState.transactions.value.toMutableList()
transactions.addAll(createdIds.map { AccountTransactionViewModel(it.key, it.value) })
uiState.transactions.value = transactions.sortedByDescending { it.valueDate }
} catch (e: Throwable) {
log.error(e) { "Could not save account transactions ${response.bookedTransactions}" }
}
try { try {
val newUser = response.user val newUser = response.user
val newUserAccountId = bankingRepository.persistUserAccount(newUser) val newUserEntity = bankingRepository.persistUserAccount(newUser)
log.info { "Saved user account $newUser" } log.info { "Saved user account $newUserEntity with ${newUserEntity.accounts.flatMap { it.bookedTransactionsEntities }.size} transactions" }
val userAccounts = uiState.userAccounts.value.toMutableList() val userAccounts = uiState.userAccounts.value.toMutableList()
userAccounts.add(UserAccountEntity(newUserAccountId, newUser)) userAccounts.add(newUserEntity)
uiState.userAccounts.value = userAccounts uiState.userAccounts.value = userAccounts
val transactions = uiState.transactions.value.toMutableList()
transactions.addAll(newUserEntity.accounts.flatMap { it.bookedTransactionsEntities }.map { AccountTransactionViewModel(it) })
uiState.transactions.value = transactions.sortedByDescending { it.valueDate }
} catch (e: Throwable) { } catch (e: Throwable) {
log.error(e) { "Could not save user account ${response.user}" } log.error(e) { "Could not save user account ${response.user}" }
} }

View File

@ -1,6 +1,9 @@
CREATE TABLE IF NOT EXISTS AccountTransaction ( CREATE TABLE IF NOT EXISTS AccountTransaction (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
userAccountId INTEGER NOT NULL,
bankAccountId INTEGER NOT NULL,
amount TEXT NOT NULL, amount TEXT NOT NULL,
currency TEXT NOT NULL, currency TEXT NOT NULL,
reference TEXT NOT NULL, reference TEXT NOT NULL,
@ -53,6 +56,8 @@ CREATE TABLE IF NOT EXISTS AccountTransaction (
insertTransaction: insertTransaction:
INSERT INTO AccountTransaction( INSERT INTO AccountTransaction(
userAccountId, bankAccountId,
amount, currency, reference, amount, currency, reference,
bookingDate, valueDate, bookingDate, valueDate,
otherPartyName, otherPartyBankCode, otherPartyAccountId, otherPartyName, otherPartyBankCode, otherPartyAccountId,
@ -79,6 +84,8 @@ INSERT INTO AccountTransaction(
transactionReferenceNumber, relatedReferenceNumber transactionReferenceNumber, relatedReferenceNumber
) )
VALUES( VALUES(
?, ?,
?, ?, ?, ?, ?, ?,
?, ?, ?, ?,
?, ?, ?, ?, ?, ?,
@ -111,5 +118,5 @@ SELECT AccountTransaction.*
FROM AccountTransaction; FROM AccountTransaction;
selectAllTransactionsAsViewModel: selectAllTransactionsAsViewModel:
SELECT id, amount, currency, reference, valueDate, otherPartyName, bookingText, sepaReference, userSetDisplayName, category SELECT id, userAccountId, bankAccountId, amount, currency, reference, valueDate, otherPartyName, bookingText, sepaReference, userSetDisplayName, category
FROM AccountTransaction; FROM AccountTransaction;

View File

@ -5,6 +5,7 @@ import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
import net.codinux.banking.client.model.* import net.codinux.banking.client.model.*
import net.codinux.banking.dataaccess.entities.AccountTransactionEntity
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
@ -15,7 +16,10 @@ class SqliteBankingRepositoryTest {
BankmeisterDb.Schema.synchronous().create(this) BankmeisterDb.Schema.synchronous().create(this)
} }
private val underTest = SqliteBankingRepository(sqlDriver) private val underTest = object : SqliteBankingRepository(sqlDriver) {
override public suspend fun persistTransaction(userAccountId: Long, bankAccountId: Long, transaction: AccountTransaction): AccountTransactionEntity =
super.persistTransaction(userAccountId, bankAccountId, transaction)
}
@Test @Test
@ -28,13 +32,8 @@ class SqliteBankingRepositoryTest {
displayIndex = 99 displayIndex = 99
} }
underTest.persistUserAccount(userAccount) val persisted = underTest.persistUserAccount(userAccount)
val result = underTest.getAllUserAccounts()
assertEquals(1, result.size)
val persisted = result.first()
assertNotNull(persisted.id) assertNotNull(persisted.id)
assertEquals(userAccount.bankCode, persisted.bankCode) assertEquals(userAccount.bankCode, persisted.bankCode)
@ -52,9 +51,9 @@ class SqliteBankingRepositoryTest {
assertEquals(userAccount.wrongCredentialsEntered, persisted.wrongCredentialsEntered) assertEquals(userAccount.wrongCredentialsEntered, persisted.wrongCredentialsEntered)
assertEquals(userAccount.displayIndex, persisted.displayIndex) assertEquals(userAccount.displayIndex, persisted.displayIndex)
assertEquals(1, persisted.accountEntities.size) assertEquals(1, persisted.accounts.size)
val persistedBankAccount = persisted.accountEntities.first() val persistedBankAccount = persisted.accounts.first()
assertNotNull(persistedBankAccount.id) assertNotNull(persistedBankAccount.id)
assertEquals(persisted.id, persistedBankAccount.userAccountId) assertEquals(persisted.id, persistedBankAccount.userAccountId)
@ -78,7 +77,7 @@ class SqliteBankingRepositoryTest {
fun saveTransaction() = runTest { fun saveTransaction() = runTest {
val transaction = AccountTransaction(Amount("12.45"), "EUR", "Lohn", LocalDate(2024, 5, 7), LocalDate(2024, 6, 15), "Dein Boss") val transaction = AccountTransaction(Amount("12.45"), "EUR", "Lohn", LocalDate(2024, 5, 7), LocalDate(2024, 6, 15), "Dein Boss")
underTest.persistAccountTransactions(listOf(transaction)) underTest.persistTransaction(1L, 1L, transaction)
val result = underTest.getAllAccountTransactions() val result = underTest.getAllAccountTransactions()
@ -99,7 +98,7 @@ class SqliteBankingRepositoryTest {
fun saveTransaction_GetAsViewModel() = runTest { fun saveTransaction_GetAsViewModel() = runTest {
val transaction = AccountTransaction(Amount("12.45"), "EUR", "Lohn", LocalDate(2024, 5, 7), LocalDate(2024, 6, 15), "Dein Boss") val transaction = AccountTransaction(Amount("12.45"), "EUR", "Lohn", LocalDate(2024, 5, 7), LocalDate(2024, 6, 15), "Dein Boss")
underTest.persistAccountTransactions(listOf(transaction)) underTest.persistTransaction(1L, 1L, transaction)
val result = underTest.getAllAccountTransactionsAsViewModel() val result = underTest.getAllAccountTransactionsAsViewModel()