Clarified that getTransactionsAsync() only retrieves the transactions of one account; also fixed data model in regard to this
This commit is contained in:
parent
e90579a1b7
commit
e87adc8499
|
@ -64,7 +64,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
jobExecutor.retrieveBasicDataLikeUsersTanMethods(context, parameter.preferredTanMethods, parameter.preferredTanMedium) { newUserInfoResponse ->
|
||||
|
||||
if (newUserInfoResponse.successful == false) { // bank parameter (FinTS server address, ...) already seem to be wrong
|
||||
callback(AddAccountResponse(context, newUserInfoResponse, bank))
|
||||
callback(AddAccountResponse(context, newUserInfoResponse))
|
||||
return@retrieveBasicDataLikeUsersTanMethods
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
jobExecutor.getAccounts(context) { getAccountsResponse ->
|
||||
|
||||
if (getAccountsResponse.successful == false) {
|
||||
callback(AddAccountResponse(context, getAccountsResponse, context.bank))
|
||||
callback(AddAccountResponse(context, getAccountsResponse))
|
||||
return@getAccounts
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
addAccountGetAccountBalancesAndTransactions(context, getAccountsResponse, callback)
|
||||
}
|
||||
else {
|
||||
val retrievedAccountData = context.bank.accounts.associateBy( { it }, { RetrievedAccountData.balanceAndTransactionsNotRequestedByUser(it) } )
|
||||
addAccountDone(context, getAccountsResponse, retrievedAccountData, callback)
|
||||
addAccountDone(context, getAccountsResponse, listOf(), callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,38 +101,34 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
callback: (AddAccountResponse) -> Unit) {
|
||||
|
||||
val bank = context.bank
|
||||
val retrievedAccountData = bank.accounts.associateBy( { it }, { RetrievedAccountData.unsuccessful(it) } ).toMutableMap()
|
||||
val retrievedTransactionsResponses = mutableListOf<GetAccountTransactionsResponse>()
|
||||
|
||||
val accountsSupportingRetrievingTransactions = bank.accounts.filter { it.supportsRetrievingBalance || it.supportsRetrievingAccountTransactions }
|
||||
val countAccountsSupportingRetrievingTransactions = accountsSupportingRetrievingTransactions.size
|
||||
var countRetrievedAccounts = 0
|
||||
|
||||
if (countAccountsSupportingRetrievingTransactions == 0) {
|
||||
addAccountDone(context, getAccountsResponse, retrievedAccountData, callback)
|
||||
return // no necessary just to make it clearer that code below doesn't get called
|
||||
addAccountDone(context, getAccountsResponse, retrievedTransactionsResponses, callback)
|
||||
return // not necessary just to make it clearer that code below doesn't get called
|
||||
}
|
||||
|
||||
accountsSupportingRetrievingTransactions.forEach { account ->
|
||||
tryGetTransactionsOfLast90DaysWithoutTan(bank, account) { response ->
|
||||
retrievedAccountData.put(account, response.retrievedData.first())
|
||||
|
||||
if (response.internalError != null) { // TODO: errors from response get lost! User then only sees "null" as error message
|
||||
//getAccountsResponse.errorMessage = response.errorMessage
|
||||
}
|
||||
tryGetAccountTransactionsOfLast90DaysWithoutTan(bank, account) { response ->
|
||||
retrievedTransactionsResponses.add(response)
|
||||
|
||||
countRetrievedAccounts++
|
||||
if (countRetrievedAccounts == countAccountsSupportingRetrievingTransactions) {
|
||||
addAccountDone(context, getAccountsResponse, retrievedAccountData, callback)
|
||||
addAccountDone(context, getAccountsResponse, retrievedTransactionsResponses, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun addAccountDone(context: JobContext, getAccountsResponse: BankResponse,
|
||||
retrievedAccountData: Map<AccountData, RetrievedAccountData>,
|
||||
retrievedTransactionsResponses: List<GetAccountTransactionsResponse>,
|
||||
callback: (AddAccountResponse) -> Unit) {
|
||||
|
||||
callback(AddAccountResponse(context, getAccountsResponse, context.bank, retrievedAccountData.values.toList()))
|
||||
callback(AddAccountResponse(context, getAccountsResponse, retrievedTransactionsResponses))
|
||||
}
|
||||
|
||||
|
||||
|
@ -143,18 +138,20 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
*
|
||||
* Check if bank supports this.
|
||||
*/
|
||||
open fun tryGetTransactionsOfLast90DaysWithoutTan(bank: BankData, account: AccountData, callback: (GetTransactionsResponse) -> Unit) {
|
||||
open fun tryGetAccountTransactionsOfLast90DaysWithoutTan(bank: BankData, account: AccountData, callback: (GetAccountTransactionsResponse) -> Unit) {
|
||||
|
||||
val ninetyDaysAgo = Date.today.addDays(-90)
|
||||
|
||||
getTransactionsAsync(GetTransactionsParameter(account, account.supportsRetrievingBalance, ninetyDaysAgo, abortIfTanIsRequired = true), bank) { response ->
|
||||
callback(response)
|
||||
}
|
||||
getAccountTransactionsAsync(createGetAccountTransactionsOfLast90DaysParameter(bank, account), callback)
|
||||
}
|
||||
|
||||
open fun getTransactionsAsync(parameter: GetTransactionsParameter, bank: BankData, callback: (GetTransactionsResponse) -> Unit) {
|
||||
protected open fun createGetAccountTransactionsOfLast90DaysParameter(bank: BankData, account: AccountData): GetAccountTransactionsParameter {
|
||||
val ninetyDaysAgo = Date.today.addDays(-90)
|
||||
|
||||
val context = JobContext(JobContextType.GetTransactions, this.callback, product, bank, parameter.account)
|
||||
return GetAccountTransactionsParameter(bank, account, account.supportsRetrievingBalance, ninetyDaysAgo, abortIfTanIsRequired = true)
|
||||
}
|
||||
|
||||
open fun getAccountTransactionsAsync(parameter: GetAccountTransactionsParameter, callback: (GetAccountTransactionsResponse) -> Unit) {
|
||||
|
||||
val context = JobContext(JobContextType.GetTransactions, this.callback, product, parameter.bank, parameter.account)
|
||||
|
||||
jobExecutor.getTransactionsAsync(context, parameter, callback)
|
||||
}
|
||||
|
|
|
@ -6,9 +6,7 @@ import net.dankito.banking.fints.model.*
|
|||
import net.dankito.banking.fints.model.mapper.ModelMapper
|
||||
import net.dankito.banking.fints.response.client.AddAccountResponse
|
||||
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
||||
import net.dankito.banking.fints.response.client.GetTransactionsResponse
|
||||
import net.dankito.banking.fints.transactions.IAccountTransactionsParser
|
||||
import net.dankito.banking.fints.transactions.Mt940AccountTransactionsParser
|
||||
import net.dankito.banking.fints.response.client.GetAccountTransactionsResponse
|
||||
import net.dankito.banking.fints.util.IBase64Service
|
||||
import net.dankito.banking.fints.util.PureKotlinBase64Service
|
||||
import net.dankito.banking.fints.util.TanMethodSelector
|
||||
|
@ -50,8 +48,8 @@ open class FinTsClientForCustomer(
|
|||
}
|
||||
|
||||
|
||||
open fun getTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
client.getTransactionsAsync(parameter, bank, callback)
|
||||
open fun getAccountTransactionsAsync(parameter: GetAccountTransactionsParameter, callback: (GetAccountTransactionsResponse) -> Unit) {
|
||||
client.getAccountTransactionsAsync(parameter, callback)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -10,10 +10,7 @@ import net.dankito.banking.fints.model.*
|
|||
import net.dankito.banking.fints.model.mapper.ModelMapper
|
||||
import net.dankito.banking.fints.response.BankResponse
|
||||
import net.dankito.banking.fints.response.InstituteSegmentId
|
||||
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
||||
import net.dankito.banking.fints.response.client.GetTanMediaListResponse
|
||||
import net.dankito.banking.fints.response.client.GetTransactionsResponse
|
||||
import net.dankito.banking.fints.response.client.GetUserTanMethodsResponse
|
||||
import net.dankito.banking.fints.response.client.*
|
||||
import net.dankito.banking.fints.response.segments.*
|
||||
import net.dankito.banking.fints.tan.FlickerCodeDecoder
|
||||
import net.dankito.banking.fints.tan.TanImageDecoder
|
||||
|
@ -178,14 +175,14 @@ open class FinTsJobExecutor(
|
|||
}
|
||||
|
||||
|
||||
open fun getTransactionsAsync(context: JobContext, parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
open fun getTransactionsAsync(context: JobContext, parameter: GetAccountTransactionsParameter, callback: (GetAccountTransactionsResponse) -> Unit) {
|
||||
|
||||
val dialogContext = context.startNewDialog()
|
||||
|
||||
initDialogWithStrongCustomerAuthentication(context) { initDialogResponse ->
|
||||
|
||||
if (initDialogResponse.successful == false) {
|
||||
callback(GetTransactionsResponse(context, initDialogResponse, RetrievedAccountData.unsuccessfulList(parameter.account)))
|
||||
callback(GetAccountTransactionsResponse(context, initDialogResponse, RetrievedAccountData.unsuccessful(parameter.account)))
|
||||
}
|
||||
else {
|
||||
// we now retrieved the fresh account information from FinTS server, use that one
|
||||
|
@ -193,7 +190,7 @@ open class FinTsJobExecutor(
|
|||
|
||||
mayGetBalance(context, parameter) { balanceResponse ->
|
||||
if (dialogContext.didBankCloseDialog) {
|
||||
callback(GetTransactionsResponse(context, balanceResponse ?: initDialogResponse, RetrievedAccountData.unsuccessfulList(parameter.account)))
|
||||
callback(GetAccountTransactionsResponse(context, balanceResponse ?: initDialogResponse, RetrievedAccountData.unsuccessful(parameter.account)))
|
||||
}
|
||||
else {
|
||||
getTransactionsAfterInitAndGetBalance(context, parameter, balanceResponse, callback)
|
||||
|
@ -207,8 +204,8 @@ open class FinTsJobExecutor(
|
|||
return context.bank.accounts.firstOrNull { it.accountIdentifier == account.accountIdentifier } ?: account
|
||||
}
|
||||
|
||||
protected open fun getTransactionsAfterInitAndGetBalance(context: JobContext, parameter: GetTransactionsParameter,
|
||||
balanceResponse: BankResponse?, callback: (GetTransactionsResponse) -> Unit) {
|
||||
protected open fun getTransactionsAfterInitAndGetBalance(context: JobContext, parameter: GetAccountTransactionsParameter,
|
||||
balanceResponse: BankResponse?, callback: (GetAccountTransactionsResponse) -> Unit) {
|
||||
var balance: Money? = balanceResponse?.getFirstSegmentById<BalanceSegment>(InstituteSegmentId.Balance)?.let {
|
||||
Money(it.balance, it.currency)
|
||||
}
|
||||
|
@ -248,15 +245,12 @@ open class FinTsJobExecutor(
|
|||
?: bookedTransactions.map { it.valueDate }.sortedBy { it.millisSinceEpoch }.firstOrNull()
|
||||
val retrievedData = RetrievedAccountData(parameter.account, successful, balance, bookedTransactions, unbookedTransactions, fromDate, parameter.toDate ?: Date.today, response.internalError)
|
||||
|
||||
callback(
|
||||
GetTransactionsResponse(context, response, listOf(retrievedData),
|
||||
if (parameter.maxCountEntries != null) parameter.isSettingMaxCountEntriesAllowedByBank else null
|
||||
)
|
||||
)
|
||||
callback(GetAccountTransactionsResponse(context, response, retrievedData,
|
||||
if (parameter.maxCountEntries != null) parameter.isSettingMaxCountEntriesAllowedByBank else null))
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun mayGetBalance(context: JobContext, parameter: GetTransactionsParameter, callback: (BankResponse?) -> Unit) {
|
||||
protected open fun mayGetBalance(context: JobContext, parameter: GetAccountTransactionsParameter, callback: (BankResponse?) -> Unit) {
|
||||
if (parameter.alsoRetrieveBalance && parameter.account.supportsRetrievingBalance) {
|
||||
val message = messageBuilder.createGetBalanceMessage(context, parameter.account)
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
}
|
||||
|
||||
|
||||
open fun createGetTransactionsMessage(context: JobContext, parameter: GetTransactionsParameter): MessageBuilderResult {
|
||||
open fun createGetTransactionsMessage(context: JobContext, parameter: GetAccountTransactionsParameter): MessageBuilderResult {
|
||||
|
||||
val result = supportsGetTransactionsMt940(parameter.account)
|
||||
|
||||
|
@ -173,7 +173,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
}
|
||||
|
||||
protected open fun createGetTransactionsMessageMt940(context: JobContext, result: MessageBuilderResult,
|
||||
parameter: GetTransactionsParameter): MessageBuilderResult {
|
||||
parameter: GetAccountTransactionsParameter): MessageBuilderResult {
|
||||
|
||||
if (parameter.maxCountEntries != null) {
|
||||
parameter.isSettingMaxCountEntriesAllowedByBank = determineIsSettingMaxCountEntriesAllowed(context.bank, InstituteSegmentId.AccountTransactionsMt940Parameters, listOf(5, 6, 7))
|
||||
|
@ -197,7 +197,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
}
|
||||
|
||||
protected open fun createGetCreditCardTransactionsMessage(context: JobContext, result: MessageBuilderResult,
|
||||
parameter: GetTransactionsParameter): MessageBuilderResult {
|
||||
parameter: GetAccountTransactionsParameter): MessageBuilderResult {
|
||||
|
||||
val segments = mutableListOf<Segment>(KreditkartenUmsaetze(generator.resetSegmentNumber(2), parameter))
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package net.dankito.banking.fints.messages.datenelemente.implementierte.account
|
|||
|
||||
import net.dankito.banking.fints.messages.Existenzstatus
|
||||
import net.dankito.banking.fints.messages.datenelemente.basisformate.NumerischesDatenelement
|
||||
import net.dankito.banking.fints.model.GetTransactionsParameter
|
||||
import net.dankito.banking.fints.model.GetAccountTransactionsParameter
|
||||
|
||||
|
||||
/**
|
||||
|
@ -11,6 +11,6 @@ import net.dankito.banking.fints.model.GetTransactionsParameter
|
|||
*/
|
||||
open class MaximaleAnzahlEintraege(maxAmount: Int?, existenzstatus: Existenzstatus) : NumerischesDatenelement(maxAmount, 4, existenzstatus) {
|
||||
|
||||
constructor(parameter: GetTransactionsParameter) : this(parameter.maxCountEntriesIfSettingItIsAllowed, if (parameter.isSettingMaxCountEntriesAllowedByBank) Existenzstatus.Optional else Existenzstatus.NotAllowed) // > 0. O: „Eingabe Anzahl Einträge erlaubt“ (BPD) = „J“. N: sonst
|
||||
constructor(parameter: GetAccountTransactionsParameter) : this(parameter.maxCountEntriesIfSettingItIsAllowed, if (parameter.isSettingMaxCountEntriesAllowedByBank) Existenzstatus.Optional else Existenzstatus.NotAllowed) // > 0. O: „Eingabe Anzahl Einträge erlaubt“ (BPD) = „J“. N: sonst
|
||||
|
||||
}
|
|
@ -9,7 +9,7 @@ import net.dankito.banking.fints.messages.datenelementgruppen.Datenelementgruppe
|
|||
import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
||||
import net.dankito.banking.fints.messages.segmente.Segment
|
||||
import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.banking.fints.model.GetTransactionsParameter
|
||||
import net.dankito.banking.fints.model.GetAccountTransactionsParameter
|
||||
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ abstract class KontoumsaetzeZeitraumMt940Base(
|
|||
segmentVersion: Int,
|
||||
segmentNumber: Int,
|
||||
account: Datenelementgruppe,
|
||||
parameter: GetTransactionsParameter
|
||||
parameter: GetAccountTransactionsParameter
|
||||
)
|
||||
: Segment(listOf(
|
||||
Segmentkopf(CustomerSegmentId.AccountTransactionsMt940, segmentVersion, segmentNumber),
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package net.dankito.banking.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.banking.fints.model.AccountData
|
||||
import net.dankito.banking.fints.model.GetTransactionsParameter
|
||||
import net.dankito.banking.fints.model.GetAccountTransactionsParameter
|
||||
|
||||
|
||||
/**
|
||||
|
@ -17,5 +16,5 @@ import net.dankito.banking.fints.model.GetTransactionsParameter
|
|||
*/
|
||||
open class KontoumsaetzeZeitraumMt940Version5(
|
||||
segmentNumber: Int,
|
||||
parameter: GetTransactionsParameter
|
||||
parameter: GetAccountTransactionsParameter
|
||||
) : KontoumsaetzeZeitraumMt940Base(5, segmentNumber, Kontoverbindung(parameter.account), parameter)
|
|
@ -1,8 +1,7 @@
|
|||
package net.dankito.banking.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.banking.fints.model.AccountData
|
||||
import net.dankito.banking.fints.model.GetTransactionsParameter
|
||||
import net.dankito.banking.fints.model.GetAccountTransactionsParameter
|
||||
|
||||
|
||||
/**
|
||||
|
@ -17,6 +16,6 @@ import net.dankito.banking.fints.model.GetTransactionsParameter
|
|||
*/
|
||||
open class KontoumsaetzeZeitraumMt940Version6(
|
||||
segmentNumber: Int,
|
||||
parameter: GetTransactionsParameter
|
||||
parameter: GetAccountTransactionsParameter
|
||||
|
||||
) : KontoumsaetzeZeitraumMt940Base(6, segmentNumber, Kontoverbindung(parameter.account), parameter)
|
|
@ -1,9 +1,8 @@
|
|||
package net.dankito.banking.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.account.KontoverbindungInternational
|
||||
import net.dankito.banking.fints.model.AccountData
|
||||
import net.dankito.banking.fints.model.BankData
|
||||
import net.dankito.banking.fints.model.GetTransactionsParameter
|
||||
import net.dankito.banking.fints.model.GetAccountTransactionsParameter
|
||||
|
||||
|
||||
/**
|
||||
|
@ -18,6 +17,6 @@ import net.dankito.banking.fints.model.GetTransactionsParameter
|
|||
*/
|
||||
open class KontoumsaetzeZeitraumMt940Version7(
|
||||
segmentNumber: Int,
|
||||
parameter: GetTransactionsParameter,
|
||||
parameter: GetAccountTransactionsParameter,
|
||||
bank: BankData
|
||||
) : KontoumsaetzeZeitraumMt940Base(7, segmentNumber, KontoverbindungInternational(parameter.account, bank), parameter)
|
|
@ -9,12 +9,12 @@ import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.Seg
|
|||
import net.dankito.banking.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.banking.fints.messages.segmente.Segment
|
||||
import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.banking.fints.model.GetTransactionsParameter
|
||||
import net.dankito.banking.fints.model.GetAccountTransactionsParameter
|
||||
|
||||
|
||||
open class KreditkartenUmsaetze(
|
||||
segmentNumber: Int,
|
||||
parameter: GetTransactionsParameter
|
||||
parameter: GetAccountTransactionsParameter
|
||||
) : Segment(listOf(
|
||||
Segmentkopf(CustomerSegmentId.CreditCardTransactions, 2, segmentNumber),
|
||||
Kontoverbindung(parameter.account),
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package net.dankito.banking.fints.model
|
||||
|
||||
import net.dankito.utils.multiplatform.Date
|
||||
import kotlin.jvm.JvmOverloads
|
||||
|
||||
|
||||
open class GetAccountTransactionsParameter @JvmOverloads constructor(
|
||||
bank: BankData,
|
||||
account: AccountData,
|
||||
alsoRetrieveBalance: Boolean = true,
|
||||
fromDate: Date? = null,
|
||||
toDate: Date? = null,
|
||||
|
||||
/**
|
||||
* Be aware this is by far not supported by all banks.
|
||||
* And it depends on the actual job if setting maxCountEntries is supported or not.
|
||||
*/
|
||||
maxCountEntries: Int? = null,
|
||||
abortIfTanIsRequired: Boolean = false,
|
||||
retrievedChunkListener: ((Collection<AccountTransaction>) -> Unit)? = null
|
||||
) : GetTransactionsParameter(bank, alsoRetrieveBalance, fromDate, toDate, maxCountEntries, abortIfTanIsRequired, retrievedChunkListener) {
|
||||
|
||||
open var account: AccountData = account
|
||||
internal set
|
||||
|
||||
|
||||
constructor(parameter: GetTransactionsParameter, account: AccountData) : this(parameter.bank, account, parameter.alsoRetrieveBalance,
|
||||
parameter.fromDate, parameter.toDate, parameter.maxCountEntries, parameter.abortIfTanIsRequired, parameter.retrievedChunkListener)
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ import kotlin.jvm.JvmOverloads
|
|||
|
||||
|
||||
open class GetTransactionsParameter @JvmOverloads constructor(
|
||||
account: AccountData,
|
||||
open val bank: BankData,
|
||||
open val alsoRetrieveBalance: Boolean = true,
|
||||
open val fromDate: Date? = null,
|
||||
open val toDate: Date? = null,
|
||||
|
@ -20,9 +20,6 @@ open class GetTransactionsParameter @JvmOverloads constructor(
|
|||
open val retrievedChunkListener: ((Collection<AccountTransaction>) -> Unit)? = null
|
||||
) {
|
||||
|
||||
open var account: AccountData = account
|
||||
internal set
|
||||
|
||||
internal open var isSettingMaxCountEntriesAllowedByBank = false
|
||||
|
||||
internal open val maxCountEntriesIfSettingItIsAllowed: Int?
|
||||
|
|
|
@ -16,18 +16,10 @@ open class RetrievedAccountData(
|
|||
|
||||
companion object {
|
||||
|
||||
fun balanceAndTransactionsNotRequestedByUser(account: AccountData): RetrievedAccountData {
|
||||
return RetrievedAccountData(account, true, null, listOf(), listOf(), null, null)
|
||||
}
|
||||
|
||||
fun unsuccessful(account: AccountData): RetrievedAccountData {
|
||||
return RetrievedAccountData(account, false, null, listOf(), listOf(), null, null)
|
||||
}
|
||||
|
||||
fun unsuccessfulList(account: AccountData): List<RetrievedAccountData> {
|
||||
return listOf(unsuccessful(account))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,12 +6,34 @@ import net.dankito.banking.fints.response.BankResponse
|
|||
|
||||
open class AddAccountResponse(
|
||||
context: JobContext,
|
||||
response: BankResponse,
|
||||
open val bank: BankData,
|
||||
retrievedData: List<RetrievedAccountData> = listOf()
|
||||
) : GetTransactionsResponse(context, response, retrievedData) {
|
||||
getAccountsResponse: BankResponse,
|
||||
open val retrievedTransactionsResponses: List<GetAccountTransactionsResponse> = listOf()
|
||||
) : FinTsClientResponse(context, getAccountsResponse) {
|
||||
|
||||
open val bank: BankData = context.bank
|
||||
|
||||
override val successful: Boolean
|
||||
get() = super.successful && bank.accounts.isNotEmpty()
|
||||
&& bank.accounts.size == retrievedTransactionsResponses.size
|
||||
&& retrievedTransactionsResponses.none { it.noTanMethodSelected }
|
||||
&& retrievedTransactionsResponses.none { it.isPinLocked }
|
||||
&& retrievedTransactionsResponses.none { it.wrongCredentialsEntered }
|
||||
&& retrievedTransactionsResponses.none { it.internalError != null }
|
||||
&& retrievedTransactionsResponses.none { it.errorMessagesFromBank.isNotEmpty() }
|
||||
|
||||
override val internalError: String?
|
||||
get() = super.internalError
|
||||
?: retrievedTransactionsResponses.mapNotNull { it.internalError }.joinToString("\r\n")
|
||||
.ifBlank { null } // if mapNotNull { it.internalError } results in an empty list, then joinToString() results in an empty string -> return null then
|
||||
|
||||
override val errorMessagesFromBank: List<String>
|
||||
get() {
|
||||
val allMessages = super.errorMessagesFromBank.toMutableList()
|
||||
allMessages.addAll(retrievedTransactionsResponses.flatMap { it.errorMessagesFromBank })
|
||||
return allMessages
|
||||
}
|
||||
|
||||
open val retrievedData: List<RetrievedAccountData>
|
||||
get() = retrievedTransactionsResponses.mapNotNull { it.retrievedData }
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package net.dankito.banking.fints.response.client
|
||||
|
||||
import net.dankito.banking.fints.model.JobContext
|
||||
import net.dankito.banking.fints.model.RetrievedAccountData
|
||||
import net.dankito.banking.fints.response.BankResponse
|
||||
|
||||
|
||||
open class GetAccountTransactionsResponse(
|
||||
context: JobContext,
|
||||
response: BankResponse,
|
||||
open val retrievedData: RetrievedAccountData?,
|
||||
/**
|
||||
* This value is only set if [GetTransactionsParameter.maxCountEntries] was set to tell caller if maxCountEntries parameter has been evaluated or not
|
||||
*/
|
||||
open var isSettingMaxCountEntriesAllowedByBank: Boolean? = null
|
||||
) : FinTsClientResponse(context, response) {
|
||||
|
||||
override val successful: Boolean
|
||||
get() = super.successful
|
||||
&& retrievedData?.successfullyRetrievedData == true
|
||||
|
||||
override val internalError: String?
|
||||
get() = super.internalError
|
||||
?: retrievedData?.errorMessage
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
return super.toString() + ": Retrieved data: $retrievedData"
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +1,35 @@
|
|||
package net.dankito.banking.fints.response.client
|
||||
|
||||
import net.dankito.banking.fints.model.JobContext
|
||||
import net.dankito.banking.fints.model.RetrievedAccountData
|
||||
import net.dankito.banking.fints.response.BankResponse
|
||||
|
||||
|
||||
open class GetTransactionsResponse(
|
||||
context: JobContext,
|
||||
response: BankResponse,
|
||||
open 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
|
||||
*/
|
||||
open var isSettingMaxCountEntriesAllowedByBank: Boolean? = null
|
||||
) : FinTsClientResponse(context, response) {
|
||||
open val retrievedResponses: List<GetAccountTransactionsResponse>,
|
||||
errorMessage: String? = null
|
||||
) : FinTsClientResponse(isSuccessful(retrievedResponses), retrievedResponses.any { it.noTanMethodSelected },
|
||||
retrievedResponses.any { it.isStrongAuthenticationRequired }, retrievedResponses.map { it.tanRequired }.firstOrNull(),
|
||||
retrievedResponses.flatMap { it.messageLogWithoutSensitiveData },
|
||||
errorMessage ?: retrievedResponses.mapNotNull { it.internalError }.joinToString("\r\n"),
|
||||
retrievedResponses.flatMap { it.errorMessagesFromBank }, retrievedResponses.any { it.isPinLocked },
|
||||
retrievedResponses.any { it.wrongCredentialsEntered }, retrievedResponses.any { it.userCancelledAction },
|
||||
retrievedResponses.any { it.tanRequiredButWeWereToldToAbortIfSo },
|
||||
retrievedResponses.any { it.isJobAllowed }, retrievedResponses.any { it.isJobAllowed },
|
||||
retrievedResponses.flatMap { it.allowedVersions }.toSet().toList(),
|
||||
retrievedResponses.flatMap { it.supportedVersions }.toSet().toList()
|
||||
) {
|
||||
|
||||
override val successful: Boolean
|
||||
get() = super.successful
|
||||
&& retrievedData.isNotEmpty()
|
||||
&& retrievedData.none { it.account.supportsRetrievingAccountTransactions && it.successfullyRetrievedData == false }
|
||||
companion object {
|
||||
|
||||
// TODO: remove again if then in AddAccountResponse errors get displayed that should or extract getRetrievingTransactionsError() and override in AddAccountResponse
|
||||
override val internalError: String?
|
||||
get() = super.internalError
|
||||
?: retrievedData.mapNotNull { it.errorMessage }.firstOrNull()
|
||||
fun isSuccessful(retrievedResponses: List<GetAccountTransactionsResponse>): Boolean {
|
||||
return retrievedResponses.isNotEmpty() &&
|
||||
retrievedResponses.none { it.retrievedData?.account?.supportsRetrievingAccountTransactions == true && it.retrievedData?.successfullyRetrievedData == false }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
open val retrievedData: List<RetrievedAccountData>
|
||||
get() = retrievedResponses.mapNotNull { it.retrievedData }
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
|
|
|
@ -132,7 +132,7 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
val context = createContext()
|
||||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(context, GetTransactionsParameter(Account))
|
||||
val result = underTest.createGetTransactionsMessage(context, GetAccountTransactionsParameter(Bank, Account))
|
||||
|
||||
// then
|
||||
expect(result.isJobAllowed).toBe(false)
|
||||
|
@ -151,7 +151,7 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
val context = createContext()
|
||||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(context, GetTransactionsParameter(account))
|
||||
val result = underTest.createGetTransactionsMessage(context, GetAccountTransactionsParameter(Bank, account))
|
||||
|
||||
// then
|
||||
expect(result.isJobAllowed).toBe(true)
|
||||
|
@ -175,7 +175,7 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
val maxCountEntries = 99
|
||||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(context, GetTransactionsParameter(account, false, fromDate, toDate, maxCountEntries))
|
||||
val result = underTest.createGetTransactionsMessage(context, GetAccountTransactionsParameter(Bank, account, false, fromDate, toDate, maxCountEntries))
|
||||
|
||||
// then
|
||||
expect(result.createdMessage).notToBeNull()
|
||||
|
@ -210,7 +210,7 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(context, // TODO: test Aufsetzpunkt / continuationId
|
||||
GetTransactionsParameter(account, false, fromDate, toDate, maxCountEntries, false))
|
||||
GetAccountTransactionsParameter(Bank, account, false, fromDate, toDate, maxCountEntries, false))
|
||||
|
||||
// then
|
||||
expect(result.createdMessage).notToBeNull()
|
||||
|
|
|
@ -15,10 +15,7 @@ import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMe
|
|||
import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse
|
||||
import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.banking.fints.model.*
|
||||
import net.dankito.banking.fints.response.client.AddAccountResponse
|
||||
import net.dankito.banking.fints.response.client.FinTsClientResponse
|
||||
import net.dankito.banking.fints.response.client.GetTanMediaListResponse
|
||||
import net.dankito.banking.fints.response.client.GetTransactionsResponse
|
||||
import net.dankito.banking.fints.response.client.*
|
||||
import net.dankito.utils.multiplatform.Date
|
||||
import net.dankito.utils.multiplatform.DateFormatter
|
||||
import net.dankito.utils.multiplatform.UUID
|
||||
|
@ -144,7 +141,7 @@ open class FinTsClientTestBase {
|
|||
fun getTransactions() {
|
||||
|
||||
// given
|
||||
val response = AtomicReference<GetTransactionsResponse>()
|
||||
val response = AtomicReference<GetAccountTransactionsResponse>()
|
||||
val countDownLatch = CountDownLatch(1)
|
||||
|
||||
underTest.addAccountAsync(Bank.toAddAccountParameter(false)) { // retrieve basic data, e.g. accounts
|
||||
|
@ -154,7 +151,7 @@ open class FinTsClientTestBase {
|
|||
// when
|
||||
|
||||
// some banks support retrieving account transactions of last 90 days without TAN
|
||||
underTest.tryGetTransactionsOfLast90DaysWithoutTan(Bank, account!!) {
|
||||
underTest.tryGetAccountTransactionsOfLast90DaysWithoutTan(Bank, account!!) {
|
||||
response.set(it)
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ open class TestAccessBankingClient(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
override fun getAccountTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
asyncRunner.runAsync {
|
||||
callback(GetTransactionsResponse(createRetrievedAccountData(parameter.account)))
|
||||
}
|
||||
|
|
|
@ -15,10 +15,7 @@ interface IBankingClient {
|
|||
|
||||
fun addAccountAsync(callback: (AddAccountResponse) -> Unit)
|
||||
|
||||
fun getTransactionsAsync(
|
||||
parameter: GetTransactionsParameter,
|
||||
callback: (GetTransactionsResponse) -> Unit
|
||||
)
|
||||
fun getAccountTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit)
|
||||
|
||||
fun transferMoneyAsync(data: TransferMoneyData, callback: (BankingClientResponse) -> Unit)
|
||||
|
||||
|
|
|
@ -371,7 +371,7 @@ open class BankingPresenter(
|
|||
getBankingClientForBank(account.bank)?.let { client ->
|
||||
val startDate = Date()
|
||||
|
||||
client.getTransactionsAsync(GetTransactionsParameter(account,true, fromDate, null, abortIfTanIsRequired, { receivedAccountTransactionChunk(account, it) } )) { response ->
|
||||
client.getAccountTransactionsAsync(GetTransactionsParameter(account,true, fromDate, null, abortIfTanIsRequired, { receivedAccountTransactionChunk(account, it) } )) { response ->
|
||||
|
||||
if (response.tanRequiredButWeWereToldToAbortIfSo == false) { // don't call retrievedAccountTransactions() if aborted due to TAN required but we told client to abort if so
|
||||
retrievedAccountTransactions(response, startDate, fromDate == null)
|
||||
|
|
|
@ -84,7 +84,8 @@ open class fints4kBankingClient(
|
|||
}
|
||||
|
||||
|
||||
override fun getTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
// we currently leave the data model of the UI layer untouched as this may changes soon anyway
|
||||
override fun getAccountTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
val account = parameter.account
|
||||
|
||||
findAccountForAccount(account) { accountData, response ->
|
||||
|
@ -97,25 +98,26 @@ open class fints4kBankingClient(
|
|||
}
|
||||
}
|
||||
else {
|
||||
val mappedParameter = GetTransactionsParameter(accountData, parameter.alsoRetrieveBalance, parameter.fromDate,
|
||||
val mappedParameter = GetAccountTransactionsParameter(fintsBank, accountData, parameter.alsoRetrieveBalance, parameter.fromDate,
|
||||
parameter.toDate, null, parameter.abortIfTanIsRequired) {
|
||||
parameter.retrievedChunkListener?.invoke(mapper.mapTransactions(account, it))
|
||||
}
|
||||
|
||||
doGetTransactionsAsync(mappedParameter, account, callback)
|
||||
doGetAccountTransactionsAsync(mappedParameter, account, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun doGetTransactionsAsync(parameter: net.dankito.banking.fints.model.GetTransactionsParameter,
|
||||
account: TypedBankAccount, callback: (GetTransactionsResponse) -> Unit) {
|
||||
client.getTransactionsAsync(parameter) { response ->
|
||||
protected open fun doGetAccountTransactionsAsync(parameter: net.dankito.banking.fints.model.GetAccountTransactionsParameter,
|
||||
account: TypedBankAccount, callback: (GetTransactionsResponse) -> Unit) {
|
||||
client.getAccountTransactionsAsync(parameter) { response ->
|
||||
handleGetTransactionsResponse(account, response, callback)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun handleGetTransactionsResponse(account: TypedBankAccount, response: net.dankito.banking.fints.response.client.GetTransactionsResponse,
|
||||
protected open fun handleGetTransactionsResponse(account: TypedBankAccount, response: net.dankito.banking.fints.response.client.GetAccountTransactionsResponse,
|
||||
callback: (GetTransactionsResponse) -> Unit) {
|
||||
// we currently leave the data model of the UI layer untouched as this may changes soon anyway
|
||||
val mappedResponse = mapper.mapResponse(account, response)
|
||||
|
||||
saveData(response)
|
||||
|
|
|
@ -32,9 +32,9 @@ open class fints4kModelMapper(protected val modelCreator: IModelCreator) {
|
|||
return AddAccountResponse(bank, map(bank, response.retrievedData), response.errorMessage, response.didBankReturnError, response.wrongCredentialsEntered, response.userCancelledAction)
|
||||
}
|
||||
|
||||
open fun mapResponse(account: TypedBankAccount, response: net.dankito.banking.fints.response.client.GetTransactionsResponse): GetTransactionsResponse {
|
||||
open fun mapResponse(account: TypedBankAccount, response: net.dankito.banking.fints.response.client.GetAccountTransactionsResponse): GetTransactionsResponse {
|
||||
|
||||
return GetTransactionsResponse(map(account.bank as TypedBankData, response.retrievedData),
|
||||
return GetTransactionsResponse(response.retrievedData?.let { map(account.bank as TypedBankData, it)?.let { listOf(it) } } ?: listOf(),
|
||||
response.errorMessage, response.didBankReturnError, response.wrongCredentialsEntered, response.userCancelledAction, response.tanRequiredButWeWereToldToAbortIfSo)
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ open class hbci4jBankingClient(
|
|||
return getTransactions(GetTransactionsParameter(account, account.supportsRetrievingBalance, ninetyDaysAgo)) // TODO: implement abortIfTanIsRequired
|
||||
}
|
||||
|
||||
override fun getTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
override fun getAccountTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
asyncRunner.runAsync {
|
||||
callback(getTransactions(parameter))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue