Extracted RetrievedAccountData, makes code way better readable
This commit is contained in:
parent
58748579b4
commit
7cb19d6f7d
|
@ -283,8 +283,9 @@ open class FinTsClient(
|
|||
protected open fun addAccountGetAccountBalancesAndTransactions(bank: BankData, newUserInfoResponse: AddAccountResponse,
|
||||
didOverwriteUserUnselectedTanProcedure: Boolean, originalAreWeThatGentleToCloseDialogs: Boolean,
|
||||
callback: (AddAccountResponse) -> Unit) {
|
||||
val transactionsOfLast90DaysResponses = mutableListOf<GetTransactionsResponse>()
|
||||
val balances = mutableMapOf<AccountData, Money>()
|
||||
// TODO: or add a default RetrievedAccountData instance for each account?
|
||||
val retrievedAccountData = mutableListOf<RetrievedAccountData>()
|
||||
var successfullyReceivedAccountTransactionsResponse = false
|
||||
|
||||
val accountSupportingRetrievingTransactions = bank.accounts.filter { it.supportsFeature(AccountFeature.RetrieveBalance) || it.supportsFeature(AccountFeature.RetrieveAccountTransactions) }
|
||||
val countAccountSupportingRetrievingTransactions = accountSupportingRetrievingTransactions.size
|
||||
|
@ -292,18 +293,21 @@ open class FinTsClient(
|
|||
|
||||
if (countAccountSupportingRetrievingTransactions == 0) {
|
||||
addAccountAfterRetrievingTransactions(bank, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure,
|
||||
originalAreWeThatGentleToCloseDialogs, transactionsOfLast90DaysResponses, balances, callback)
|
||||
originalAreWeThatGentleToCloseDialogs, retrievedAccountData, successfullyReceivedAccountTransactionsResponse, callback)
|
||||
}
|
||||
|
||||
accountSupportingRetrievingTransactions.forEach { account ->
|
||||
tryGetTransactionsOfLast90DaysWithoutTan(bank, account) { response ->
|
||||
transactionsOfLast90DaysResponses.add(response)
|
||||
response.balance?.let { balances.put(account, it) }
|
||||
retrievedAccountData.addAll(response.retrievedData)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
successfullyReceivedAccountTransactionsResponse = true
|
||||
}
|
||||
|
||||
countRetrievedAccounts++
|
||||
if (countRetrievedAccounts == countAccountSupportingRetrievingTransactions) {
|
||||
addAccountAfterRetrievingTransactions(bank, newUserInfoResponse, didOverwriteUserUnselectedTanProcedure, originalAreWeThatGentleToCloseDialogs,
|
||||
transactionsOfLast90DaysResponses, balances, callback)
|
||||
retrievedAccountData, successfullyReceivedAccountTransactionsResponse, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,21 +315,16 @@ open class FinTsClient(
|
|||
|
||||
protected open fun addAccountAfterRetrievingTransactions(bank: BankData, newUserInfoResponse: AddAccountResponse,
|
||||
didOverwriteUserUnselectedTanProcedure: Boolean, originalAreWeThatGentleToCloseDialogs: Boolean,
|
||||
transactionsOfLast90DaysResponses: MutableList<GetTransactionsResponse>,
|
||||
balances: MutableMap<AccountData, Money>, callback: (AddAccountResponse) -> Unit) {
|
||||
retrievedAccountData: List<RetrievedAccountData>, successfullyReceivedAccountTransactionsResponse: Boolean,
|
||||
callback: (AddAccountResponse) -> Unit) {
|
||||
if (didOverwriteUserUnselectedTanProcedure) {
|
||||
bank.resetSelectedTanProcedure()
|
||||
}
|
||||
|
||||
areWeThatGentleToCloseDialogs = originalAreWeThatGentleToCloseDialogs
|
||||
|
||||
val supportsRetrievingTransactionsOfLast90DaysWithoutTan = transactionsOfLast90DaysResponses.firstOrNull { it.isSuccessful } != null
|
||||
val unbookedTransactions = transactionsOfLast90DaysResponses.flatMap { it.unbookedTransactions }
|
||||
val bookedTransactions = transactionsOfLast90DaysResponses.flatMap { it.bookedTransactions }
|
||||
|
||||
// TODO: to evaluate if adding account has been successful also check if count accounts > 0
|
||||
callback(AddAccountResponse(newUserInfoResponse.toResponse(), bank, supportsRetrievingTransactionsOfLast90DaysWithoutTan,
|
||||
bookedTransactions, unbookedTransactions, balances))
|
||||
callback(AddAccountResponse(newUserInfoResponse.toResponse(), bank, successfullyReceivedAccountTransactionsResponse, retrievedAccountData))
|
||||
}
|
||||
|
||||
|
||||
|
@ -348,6 +347,7 @@ open class FinTsClient(
|
|||
open fun getTransactionsAsync(parameter: GetTransactionsParameter, bank: BankData,
|
||||
account: AccountData, callback: (GetTransactionsResponse) -> Unit) {
|
||||
|
||||
// TODO: or add default RetrievedAccountData if an error occurs?
|
||||
val dialogContext = DialogContext(bank, product)
|
||||
|
||||
initDialog(dialogContext) { initDialogResponse ->
|
||||
|
@ -374,10 +374,10 @@ open class FinTsClient(
|
|||
val balance: Money? = balanceResponse.getFirstSegmentById<BalanceSegment>(InstituteSegmentId.Balance)?.let {
|
||||
Money(it.balance, it.currency)
|
||||
}
|
||||
val retrievedData = RetrievedAccountData(account, balance, listOf(), listOf())
|
||||
|
||||
val message = messageBuilder.createGetTransactionsMessage(parameter, account, dialogContext)
|
||||
|
||||
val bookedTransactions = mutableSetOf<AccountTransaction>() // some banks like Postbank return some transactions multiple times -> remove these
|
||||
var remainingMt940String = ""
|
||||
|
||||
dialogContext.abortIfTanIsRequired = parameter.abortIfTanIsRequired
|
||||
|
@ -386,24 +386,19 @@ open class FinTsClient(
|
|||
response.getFirstSegmentById<ReceivedAccountTransactions>(InstituteSegmentId.AccountTransactionsMt940)?.let { transactionsSegment ->
|
||||
val (chunkTransaction, remainder) = mt940Parser.parseTransactionsChunk(remainingMt940String + transactionsSegment.bookedTransactionsString, account)
|
||||
|
||||
bookedTransactions.addAll(chunkTransaction)
|
||||
retrievedData.addBookedTransactions(chunkTransaction)
|
||||
remainingMt940String = remainder
|
||||
|
||||
parameter.retrievedChunkListener?.invoke(bookedTransactions)
|
||||
parameter.retrievedChunkListener?.invoke(retrievedData.bookedTransactions)
|
||||
}
|
||||
}
|
||||
|
||||
getAndHandleResponseForMessage(message, dialogContext) { response ->
|
||||
closeDialog(dialogContext)
|
||||
|
||||
callback(GetTransactionsResponse(
|
||||
response,
|
||||
bookedTransactions.toList(),
|
||||
listOf(), // TODO: implement parsing MT942
|
||||
balance,
|
||||
callback(GetTransactionsResponse(response, listOf(retrievedData),
|
||||
if (parameter.maxCountEntries != null) parameter.isSettingMaxCountEntriesAllowedByBank else null
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package net.dankito.banking.fints.model
|
||||
|
||||
|
||||
open class RetrievedAccountData(
|
||||
val accountData: AccountData,
|
||||
val balance: Money?,
|
||||
var bookedTransactions: Collection<AccountTransaction>,
|
||||
var unbookedTransactions: List<Any>
|
||||
) {
|
||||
|
||||
open fun addBookedTransactions(transactions: List<AccountTransaction>) {
|
||||
val bookedTransactions = this.bookedTransactions.toMutableList() // some banks like Postbank return some transactions multiple times -> remove these
|
||||
|
||||
bookedTransactions.addAll(transactions)
|
||||
|
||||
this.bookedTransactions = bookedTransactions
|
||||
}
|
||||
|
||||
}
|
|
@ -8,9 +8,5 @@ open class AddAccountResponse(
|
|||
response: Response,
|
||||
val bank: BankData,
|
||||
val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false,
|
||||
bookedTransactionsOfLast90Days: List<AccountTransaction> = listOf(),
|
||||
unbookedTransactionsOfLast90Days: List<Any> = listOf(),
|
||||
val balances: Map<AccountData, Money> = mapOf()
|
||||
)
|
||||
: GetTransactionsResponse(response, bookedTransactionsOfLast90Days, unbookedTransactionsOfLast90Days,
|
||||
Money(Amount.Zero, balances.values.firstOrNull()?.currency?.code ?: "EUR")) // TODO: sum balances
|
||||
retrievedData: List<RetrievedAccountData> = listOf()
|
||||
) : GetTransactionsResponse(response, retrievedData)
|
|
@ -1,15 +1,12 @@
|
|||
package net.dankito.banking.fints.response.client
|
||||
|
||||
import net.dankito.banking.fints.model.AccountTransaction
|
||||
import net.dankito.banking.fints.model.Money
|
||||
import net.dankito.banking.fints.model.RetrievedAccountData
|
||||
import net.dankito.banking.fints.response.Response
|
||||
|
||||
|
||||
open class GetTransactionsResponse(
|
||||
response: Response,
|
||||
val bookedTransactions: List<AccountTransaction> = listOf(),
|
||||
val unbookedTransactions: List<Any> = listOf(),
|
||||
val balance: Money? = null,
|
||||
val retrievedData: List<RetrievedAccountData> = listOf(),
|
||||
/**
|
||||
* This value is only set if [GetTransactionsParameter.maxCountEntries] was set to tell caller if maxCountEntries parameter has been evaluated or not
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package net.dankito.banking.ui.model
|
||||
|
||||
import net.dankito.utils.multiplatform.BigDecimal
|
||||
|
||||
|
||||
open class RetrievedAccountData(
|
||||
val account: TypedBankAccount,
|
||||
val balance: BigDecimal?,
|
||||
var bookedTransactions: Collection<IAccountTransaction>,
|
||||
var unbookedTransactions: List<Any>
|
||||
)
|
|
@ -9,12 +9,9 @@ open class AddAccountResponse(
|
|||
errorToShowToUser: String?,
|
||||
val customer: TypedCustomer,
|
||||
val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false,
|
||||
val bookedTransactionsOfLast90Days: Map<TypedBankAccount, List<IAccountTransaction>> = mapOf(),
|
||||
val unbookedTransactionsOfLast90Days: Map<TypedBankAccount, List<Any>> = mapOf(),
|
||||
val balances: Map<TypedBankAccount, BigDecimal> = mapOf(),
|
||||
val retrievedData: List<RetrievedAccountData> = listOf(),
|
||||
userCancelledAction: Boolean = false
|
||||
)
|
||||
: BankingClientResponse(isSuccessful, errorToShowToUser, userCancelledAction) {
|
||||
) : BankingClientResponse(isSuccessful, errorToShowToUser, userCancelledAction) {
|
||||
|
||||
override fun toString(): String {
|
||||
return customer.toString() + " " + super.toString()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package net.dankito.banking.ui.model.responses
|
||||
|
||||
import net.dankito.utils.multiplatform.BigDecimal
|
||||
import net.dankito.banking.ui.model.IAccountTransaction
|
||||
import net.dankito.banking.ui.model.RetrievedAccountData
|
||||
import net.dankito.banking.ui.model.TypedBankAccount
|
||||
|
||||
|
||||
|
@ -9,10 +8,7 @@ open class GetTransactionsResponse(
|
|||
val bankAccount: TypedBankAccount,
|
||||
isSuccessful: Boolean,
|
||||
errorToShowToUser: String?,
|
||||
val bookedTransactions: List<IAccountTransaction> = listOf(),
|
||||
val unbookedTransactions: List<Any> = listOf(),
|
||||
val balance: BigDecimal? = null,
|
||||
val retrievedData: List<RetrievedAccountData> = listOf(),
|
||||
userCancelledAction: Boolean = false,
|
||||
val tanRequiredButWeWereToldToAbortIfSo: Boolean = false
|
||||
)
|
||||
: BankingClientResponse(isSuccessful, errorToShowToUser, userCancelledAction)
|
||||
) : BankingClientResponse(isSuccessful, errorToShowToUser, userCancelledAction)
|
||||
|
|
|
@ -160,21 +160,11 @@ open class BankingPresenter(
|
|||
|
||||
persistAccountOffUiThread(account)
|
||||
|
||||
if (response.supportsRetrievingTransactionsOfLast90DaysWithoutTan) {
|
||||
response.bookedTransactionsOfLast90Days.keys.forEach { bankAccount ->
|
||||
retrievedAccountTransactions(GetTransactionsResponse(bankAccount, true, null,
|
||||
response.bookedTransactionsOfLast90Days[bankAccount] ?: listOf(),
|
||||
response.unbookedTransactionsOfLast90Days[bankAccount] ?: listOf(),
|
||||
response.balances[bankAccount]),
|
||||
startDate, false
|
||||
response.retrievedData.forEach { retrievedData ->
|
||||
retrievedAccountTransactions(GetTransactionsResponse(retrievedData.account, true, null,
|
||||
listOf(retrievedData)), startDate, false
|
||||
)
|
||||
}
|
||||
}
|
||||
else { // TODO: find a better way to update balances if transactions couldn't be retrieved
|
||||
response.balances.keys.forEach { bankAccount ->
|
||||
updateBalance(bankAccount, response.balances[bankAccount]!!)
|
||||
}
|
||||
}
|
||||
|
||||
findIconForBankAsync(account)
|
||||
}
|
||||
|
@ -346,13 +336,15 @@ open class BankingPresenter(
|
|||
|
||||
protected open fun retrievedAccountTransactions(response: GetTransactionsResponse, startDate: Date, didFetchAllTransactions: Boolean) {
|
||||
if (response.isSuccessful) {
|
||||
response.bankAccount.lastRetrievedTransactionsTimestamp = startDate
|
||||
response.retrievedData.forEach { retrievedData ->
|
||||
retrievedData.account.lastRetrievedTransactionsTimestamp = startDate
|
||||
|
||||
if (didFetchAllTransactions) {
|
||||
response.bankAccount.haveAllTransactionsBeenFetched = true
|
||||
retrievedData.account.haveAllTransactionsBeenFetched = true
|
||||
}
|
||||
|
||||
updateAccountTransactionsAndBalances(response)
|
||||
updateAccountTransactionsAndBalances(retrievedData)
|
||||
}
|
||||
}
|
||||
|
||||
callRetrievedAccountTransactionsResponseListener(response)
|
||||
|
@ -363,22 +355,20 @@ open class BankingPresenter(
|
|||
asyncRunner.runAsync { // don't block retrieving next chunk by blocked saving to db / json
|
||||
updateAccountTransactions(bankAccount, accountTransactionsChunk)
|
||||
|
||||
callRetrievedAccountTransactionsResponseListener(GetTransactionsResponse(bankAccount, true, null, accountTransactionsChunk))
|
||||
callRetrievedAccountTransactionsResponseListener(GetTransactionsResponse(bankAccount, true, null, listOf(RetrievedAccountData(bankAccount, null, accountTransactionsChunk, listOf()))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun updateAccountTransactionsAndBalances(response: GetTransactionsResponse) {
|
||||
val bankAccount = response.bankAccount
|
||||
protected open fun updateAccountTransactionsAndBalances(retrievedData: RetrievedAccountData) {
|
||||
updateAccountTransactions(retrievedData.account, retrievedData.bookedTransactions, retrievedData.unbookedTransactions)
|
||||
|
||||
updateAccountTransactions(bankAccount, response.bookedTransactions, response.unbookedTransactions)
|
||||
|
||||
response.balance?.let {
|
||||
updateBalance(bankAccount, it)
|
||||
retrievedData.balance?.let {
|
||||
updateBalance(retrievedData.account, it)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun updateAccountTransactions(bankAccount: TypedBankAccount, bookedTransactions: List<IAccountTransaction>, unbookedTransactions: List<Any>? = null) {
|
||||
protected open fun updateAccountTransactions(bankAccount: TypedBankAccount, bookedTransactions: Collection<IAccountTransaction>, unbookedTransactions: List<Any>? = null) {
|
||||
val knownAccountTransactions = bankAccount.bookedTransactions.map { it.transactionIdentifier }
|
||||
|
||||
val newBookedTransactions = bookedTransactions.filterNot { knownAccountTransactions.contains(it.transactionIdentifier) }
|
||||
|
|
|
@ -15,45 +15,55 @@ import net.dankito.banking.fints.model.BankData
|
|||
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
||||
import net.dankito.banking.fints.response.segments.AccountType
|
||||
import net.dankito.banking.ui.model.mapper.IModelCreator
|
||||
import net.dankito.utils.multiplatform.log.LoggerFactory
|
||||
|
||||
|
||||
open class fints4kModelMapper(protected val modelCreator: IModelCreator) {
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(fints4kModelMapper::class)
|
||||
}
|
||||
|
||||
|
||||
open fun mapResponse(response: FinTsClientResponse): BankingClientResponse {
|
||||
return BankingClientResponse(response.isSuccessful, mapErrorToShowToUser(response), response.userCancelledAction)
|
||||
}
|
||||
|
||||
open fun mapResponse(customer: TypedCustomer, response: net.dankito.banking.fints.response.client.AddAccountResponse): AddAccountResponse {
|
||||
val balances = response.balances.mapKeys { findMatchingBankAccount(customer, it.key) }.filter { it.key != null }
|
||||
.mapValues { it.value.toBigDecimal() } as Map<TypedBankAccount, BigDecimal>
|
||||
|
||||
val bookedTransactions = response.bookedTransactions.associateBy { it.account }
|
||||
val mappedBookedTransactions = mutableMapOf<TypedBankAccount, List<IAccountTransaction>>()
|
||||
|
||||
bookedTransactions.keys.forEach { accountData ->
|
||||
findMatchingBankAccount(customer, accountData)?.let { bankAccount ->
|
||||
mappedBookedTransactions.put(bankAccount, mapTransactions(bankAccount, response.bookedTransactions))
|
||||
}
|
||||
}
|
||||
|
||||
return AddAccountResponse(response.isSuccessful, mapErrorToShowToUser(response),
|
||||
customer, response.supportsRetrievingTransactionsOfLast90DaysWithoutTan,
|
||||
mappedBookedTransactions,
|
||||
mapOf(), // TODO: map unbooked transactions
|
||||
balances,
|
||||
map(customer, response.retrievedData),
|
||||
response.userCancelledAction)
|
||||
}
|
||||
|
||||
open fun mapResponse(bankAccount: TypedBankAccount, response: net.dankito.banking.fints.response.client.GetTransactionsResponse): GetTransactionsResponse {
|
||||
|
||||
return GetTransactionsResponse(bankAccount, response.isSuccessful, mapErrorToShowToUser(response),
|
||||
mapTransactions(bankAccount, response.bookedTransactions),
|
||||
listOf(), // TODO: map unbooked transactions
|
||||
response.balance?.toBigDecimal(),
|
||||
map(bankAccount.customer as TypedCustomer, response.retrievedData),
|
||||
response.userCancelledAction, response.tanRequiredButWeWereToldToAbortIfSo)
|
||||
}
|
||||
|
||||
open fun map(customer: TypedCustomer, retrievedData: List<net.dankito.banking.fints.model.RetrievedAccountData>): List<RetrievedAccountData> {
|
||||
return retrievedData.mapNotNull { map(customer, it) }
|
||||
}
|
||||
|
||||
open fun map(customer: TypedCustomer, retrievedData: net.dankito.banking.fints.model.RetrievedAccountData): RetrievedAccountData? {
|
||||
val account = findMatchingBankAccount(customer, retrievedData.accountData)
|
||||
|
||||
if (account == null) {
|
||||
log.error("No matching account found for ${retrievedData.accountData}. Has there an account been added we didn't map yet?")
|
||||
return null
|
||||
}
|
||||
|
||||
return RetrievedAccountData(
|
||||
account,
|
||||
retrievedData.balance?.toBigDecimal(),
|
||||
mapTransactions(account, retrievedData.bookedTransactions),
|
||||
listOf()
|
||||
)
|
||||
}
|
||||
|
||||
open fun mapErrorToShowToUser(response: FinTsClientResponse): String? {
|
||||
val errorMessage = response.errorMessage
|
||||
|
||||
|
|
Loading…
Reference in New Issue