Implemented persisting TanMethods

This commit is contained in:
dankito 2024-09-09 01:34:37 +02:00
parent a2dbe912d4
commit 0fff3f2c97
4 changed files with 112 additions and 11 deletions

View File

@ -4,10 +4,12 @@ import app.cash.sqldelight.db.SqlDriver
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
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 net.codinux.banking.client.model.tan.AllowedTanFormat
import net.codinux.banking.dataaccess.entities.BankAccountEntity import net.codinux.banking.client.model.tan.TanMethod
import net.codinux.banking.dataaccess.entities.UserEntity import net.codinux.banking.client.model.tan.TanMethodType
import net.codinux.banking.dataaccess.entities.*
import net.codinux.banking.ui.model.AccountTransactionViewModel import net.codinux.banking.ui.model.AccountTransactionViewModel
import net.codinux.log.Log
import net.codinux.log.logger import net.codinux.log.logger
import kotlin.enums.EnumEntries import kotlin.enums.EnumEntries
import kotlin.js.JsName import kotlin.js.JsName
@ -28,9 +30,10 @@ open class SqliteBankingRepository(
override fun getAllUsers(): List<UserEntity> { override fun getAllUsers(): List<UserEntity> {
val bankAccounts = getAllBankAccounts().groupBy { it.userId } val bankAccounts = getAllBankAccounts().groupBy { it.userId }
val tanMethods = getAllTanMethods().groupBy { it.userId }
return userQueries.selectAllUsers { id, bankCode, loginName, password, bankName, bic, customerName, userId, selectedTanMethodIdentifier, selectedTanMediumIdentifier, bankingGroup, serverAddress, userSetDisplayName, displayIndex, iconUrl, wrongCredentialsEntered -> return userQueries.selectAllUsers { id, bankCode, loginName, password, bankName, bic, customerName, userId, selectedTanMethodIdentifier, selectedTanMediumIdentifier, bankingGroup, serverAddress, userSetDisplayName, displayIndex, iconUrl, wrongCredentialsEntered ->
UserEntity(id, bankCode, loginName, password, bankName, bic, customerName, userId, bankAccounts[id] ?: emptyList(), selectedTanMethodIdentifier, emptyList(), selectedTanMediumIdentifier, emptyList(), UserEntity(id, bankCode, loginName, password, bankName, bic, customerName, userId, bankAccounts[id] ?: emptyList(), selectedTanMethodIdentifier, tanMethods[id] ?: emptyList(), selectedTanMediumIdentifier, emptyList(),
bankingGroup?.let { BankingGroup.valueOf(it) }, serverAddress, userSetDisplayName, displayIndex.toInt(), iconUrl, wrongCredentialsEntered) bankingGroup?.let { BankingGroup.valueOf(it) }, serverAddress, userSetDisplayName, displayIndex.toInt(), iconUrl, wrongCredentialsEntered)
}.executeAsList() }.executeAsList()
} }
@ -46,12 +49,13 @@ open class SqliteBankingRepository(
val bankAccounts = persistBankAccounts(userId, user.accounts) val bankAccounts = persistBankAccounts(userId, user.accounts)
UserEntity(userId, user, bankAccounts) val tanMethods = persistTanMethods(userId, user.tanMethods)
UserEntity(userId, user, bankAccounts, tanMethods)
} }
} }
fun getAllBankAccounts(): List<BankAccountEntity> = userQueries.selectAllBankAccounts { id, userId, identifier, subAccountNumber, iban, productName, accountHolderName, type, currency, accountLimit, isAccountTypeSupportedByApplication, features, balance, serverTransactionsRetentionDays, lastTransactionsRetrievalTime, retrievedTransactionsFrom, userSetDisplayName, displayIndex, hideAccount, includeInAutomaticAccountsUpdate -> fun getAllBankAccounts(): List<BankAccountEntity> = userQueries.selectAllBankAccounts { id, userId, identifier, subAccountNumber, iban, productName, accountHolderName, type, currency, accountLimit, isAccountTypeSupportedByApplication, features, balance, serverTransactionsRetentionDays, lastTransactionsRetrievalTime, retrievedTransactionsFrom, userSetDisplayName, displayIndex, hideAccount, includeInAutomaticAccountsUpdate ->
BankAccountEntity( BankAccountEntity(
id, userId, id, userId,
@ -107,6 +111,39 @@ open class SqliteBankingRepository(
} }
private fun getAllTanMethods(): List<TanMethodEntity> = userQueries.selectAllTanMethods { id, userId, displayName, type, identifier, maxTanInputLength, allowedTanFormat ->
TanMethodEntity(
id,
userId,
displayName,
mapToEnum(type, TanMethodType.entries),
identifier,
mapToInt(maxTanInputLength),
mapToEnum(allowedTanFormat, AllowedTanFormat.entries)
)
}.executeAsList()
private suspend fun persistTanMethods(userId: Long, tanMethods: List<TanMethod>): List<TanMethodEntity> =
tanMethods.map { persistTanMethod(userId, it) }
private suspend fun persistTanMethod(userId: Long, tanMethod: TanMethod): TanMethodEntity {
userQueries.insertTanMethod(
userId,
tanMethod.displayName,
mapEnum(tanMethod.type),
tanMethod.identifier,
mapInt(tanMethod.maxTanInputLength),
mapEnum(tanMethod.allowedTanFormat)
)
val tanMethodId = getLastInsertedId()
return TanMethodEntity(tanMethodId, userId, tanMethod)
}
override fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel> = override fun getAllAccountTransactionsAsViewModel(): List<AccountTransactionViewModel> =
accountTransactionQueries.selectAllTransactionsAsViewModel { id, userId, bankAccountId, amount, currency, reference, valueDate, otherPartyName, postingText, 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) AccountTransactionViewModel(id, userId, bankAccountId, mapToAmount(amount), currency, reference, mapToDate(valueDate), otherPartyName, postingText, userSetDisplayName, category)
@ -284,7 +321,10 @@ open class SqliteBankingRepository(
private fun <E : Enum<E>> mapEnum(enum: Enum<E>): String = enum.name private fun <E : Enum<E>> mapEnum(enum: Enum<E>): String = enum.name
private fun <E : Enum<E>> mapToEnum(enumName: String, values: EnumEntries<E>): E? { private fun <E : Enum<E>> mapToEnum(enumName: String, values: EnumEntries<E>): E =
values.first { it.name == enumName }
private fun <E : Enum<E>> mapToEnumNullable(enumName: String, values: EnumEntries<E>): E? {
val mapped = values.firstOrNull { it.name == enumName } val mapped = values.firstOrNull { it.name == enumName }
if (mapped == null) { if (mapped == null) {
@ -298,7 +338,7 @@ open class SqliteBankingRepository(
enums.joinToString(",") { it.name } enums.joinToString(",") { it.name }
private fun <E : Enum<E>> mapEnumSet(enumsString: String, values: EnumEntries<E>): Set<E> = private fun <E : Enum<E>> mapEnumSet(enumsString: String, values: EnumEntries<E>): Set<E> =
enumsString.split(',').filterNot { it.isBlank() }.mapNotNull { mapToEnum(it, values) }.toSet() enumsString.split(',').filterNot { it.isBlank() }.mapNotNull { mapToEnumNullable(it, values) }.toSet()
@JvmName("mapIntNullable") @JvmName("mapIntNullable")
@JsName("mapIntNullable") @JsName("mapIntNullable")

View File

@ -0,0 +1,21 @@
package net.codinux.banking.dataaccess.entities
import net.codinux.banking.client.model.tan.AllowedTanFormat
import net.codinux.banking.client.model.tan.TanMethod
import net.codinux.banking.client.model.tan.TanMethodType
class TanMethodEntity(
val id: Long,
val userId: Long,
displayName: String,
type: TanMethodType,
identifier: String,
maxTanInputLength: Int? = null,
allowedTanFormat: AllowedTanFormat = AllowedTanFormat.Alphanumeric
) : TanMethod(displayName, type, identifier, maxTanInputLength, allowedTanFormat) {
constructor(id: Long, userId: Long, tanMethod: TanMethod)
: this(id, userId, tanMethod.displayName, tanMethod.type, tanMethod.identifier, tanMethod.maxTanInputLength, tanMethod.allowedTanFormat)
}

View File

@ -21,7 +21,7 @@ class UserEntity(
override val accounts: List<BankAccountEntity> = emptyList(), override val accounts: List<BankAccountEntity> = emptyList(),
selectedTanMethodIdentifier: String? = null, selectedTanMethodIdentifier: String? = null,
tanMethods: List<TanMethod> = listOf(), override val tanMethods: List<TanMethodEntity> = listOf(),
selectedTanMediumIdentifier: String? = null, selectedTanMediumIdentifier: String? = null,
tanMedia: List<TanMedium> = listOf(), tanMedia: List<TanMedium> = listOf(),
@ -45,11 +45,11 @@ class UserEntity(
} }
constructor(id: Long, user: User, bankAccounts: List<BankAccountEntity>) : this( constructor(id: Long, user: User, bankAccounts: List<BankAccountEntity>, tanMethods: List<TanMethodEntity>) : 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,
bankAccounts, bankAccounts,
user.selectedTanMethodIdentifier, user.tanMethods, user.selectedTanMediumIdentifier, user.tanMedia, user.selectedTanMethodIdentifier, tanMethods, user.selectedTanMediumIdentifier, user.tanMedia,
user.bankingGroup, user.serverAddress, user.bankingGroup, user.serverAddress,
user.userSetDisplayName, user.displayIndex, user.userSetDisplayName, user.displayIndex,
user.iconUrl, user.wrongCredentialsEntered, user.iconUrl, user.wrongCredentialsEntered,

View File

@ -141,6 +141,46 @@ SELECT BankAccount.*
FROM BankAccount; FROM BankAccount;
CREATE TABLE IF NOT EXISTS TanMethod (
id INTEGER PRIMARY KEY AUTOINCREMENT,
userId INTEGER NOT NULL,
displayName TEXT NOT NULL,
type TEXT NOT NULL,
identifier TEXT NOT NULL,
maxTanInputLength INTEGER ,
allowedTanFormat TEXT NOT NULL
);
insertTanMethod:
INSERT INTO TanMethod(
userId,
displayName,
type,
identifier,
maxTanInputLength,
allowedTanFormat
)
VALUES (
?,
?,
?,
?,
?,
?
);
selectAllTanMethods:
SELECT TanMethod.*
FROM TanMethod;
-- TODO: find a better place for this cross-cutting concern: -- TODO: find a better place for this cross-cutting concern:
getLastInsertedId: getLastInsertedId:
SELECT last_insert_rowid(); SELECT last_insert_rowid();