diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt index 94a112cc..d98dbaa7 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt @@ -133,7 +133,7 @@ class HomeFragment : Fragment() { presenter.addAccountsChangedListener { updateMenuItemsStateAndTransactionsToDisplay() } // on account addition or deletion may menu items' state changes presenter.addSelectedBankAccountsChangedListener { updateMenuItemsStateAndTransactionsToDisplay() } - presenter.addRetrievedAccountTransactionsResponseListener { _, response -> + presenter.addRetrievedAccountTransactionsResponseListener { response -> handleGetTransactionsResponse(response) } diff --git a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt index d77abbf5..0b4c2a42 100644 --- a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt +++ b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt @@ -32,7 +32,7 @@ open class AccountTransactionsView(private val presenter: BankingPresenter) : Vi init { presenter.addSelectedBankAccountsChangedListener { handleSelectedBankAccountsChanged(it) } - presenter.addRetrievedAccountTransactionsResponseListener { _, response -> + presenter.addRetrievedAccountTransactionsResponseListener { response -> handleGetTransactionsResponseOffUiThread(response) } diff --git a/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/AddAccountResponse.kt b/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/AddAccountResponse.kt index caaa9fa1..064b14fe 100644 --- a/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/AddAccountResponse.kt +++ b/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/AddAccountResponse.kt @@ -11,13 +11,13 @@ open class AddAccountResponse( errorToShowToUser: String?, val account: Account, val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false, - bookedTransactionsOfLast90Days: Map> = mapOf(), - unbookedTransactionsOfLast90Days: Map> = mapOf(), - balances: Map = mapOf(), + val bookedTransactionsOfLast90Days: Map> = mapOf(), + val unbookedTransactionsOfLast90Days: Map> = mapOf(), + val balances: Map = mapOf(), error: Exception? = null, userCancelledAction: Boolean = false ) - : GetTransactionsResponse(isSuccessful, errorToShowToUser, bookedTransactionsOfLast90Days, unbookedTransactionsOfLast90Days, balances, error, userCancelledAction) { + : BankingClientResponse(isSuccessful, errorToShowToUser, error, userCancelledAction) { override fun toString(): String { return account.toString() + " " + super.toString() diff --git a/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/GetTransactionsResponse.kt b/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/GetTransactionsResponse.kt index e1052fc9..fd08ceea 100644 --- a/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/GetTransactionsResponse.kt +++ b/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/model/responses/GetTransactionsResponse.kt @@ -6,11 +6,12 @@ import java.math.BigDecimal open class GetTransactionsResponse( + val bankAccount: BankAccount, isSuccessful: Boolean, errorToShowToUser: String?, - val bookedTransactions: Map> = mapOf(), - val unbookedTransactions: Map> = mapOf(), - val balances: Map = mapOf(), + val bookedTransactions: List = listOf(), + val unbookedTransactions: List = listOf(), + val balance: BigDecimal? = null, error: Exception? = null, userCancelledAction: Boolean = false, val tanRequiredButWeWereToldToAbortIfSo: Boolean = false diff --git a/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt b/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt index e0bc81d2..0955366a 100644 --- a/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt +++ b/ui/BankingUiCommon/src/main/java/net/dankito/banking/ui/presenter/BankingPresenter.kt @@ -67,7 +67,7 @@ open class BankingPresenter( protected val accountsChangedListeners = mutableListOf<(List) -> Unit>() - protected val retrievedAccountTransactionsResponseListeners = mutableListOf<(BankAccount, GetTransactionsResponse) -> Unit>() + protected val retrievedAccountTransactionsResponseListeners = mutableListOf<(GetTransactionsResponse) -> Unit>() protected val selectedBankAccountsChangedListeners = mutableListOf<(List) -> Unit>() @@ -167,8 +167,12 @@ open class BankingPresenter( persistAccount(account) if (response.supportsRetrievingTransactionsOfLast90DaysWithoutTan) { - response.bookedTransactions.keys.forEach { bankAccount -> - retrievedAccountTransactions(bankAccount, startDate, response) + response.bookedTransactionsOfLast90Days.keys.forEach { bankAccount -> + retrievedAccountTransactions(startDate, GetTransactionsResponse(bankAccount, true, null, + response.bookedTransactionsOfLast90Days[bankAccount] ?: listOf(), + response.unbookedTransactionsOfLast90Days[bankAccount] ?: listOf(), + response.balances[bankAccount]) + ) } } @@ -279,7 +283,7 @@ open class BankingPresenter( client.getTransactionsAsync(bankAccount, GetTransactionsParameter(true, fromDate, null, abortIfTanIsRequired, { receivedAccountsTransactionChunk(bankAccount, 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(bankAccount, startDate, response) + retrievedAccountTransactions(startDate, response) } callback(response) @@ -311,40 +315,38 @@ open class BankingPresenter( fetchAccountTransactionsAsync(bankAccount, fromDate, abortIfTanIsRequired, callback) } - protected open fun retrievedAccountTransactions(bankAccount: BankAccount, startDate: Date, response: GetTransactionsResponse) { + protected open fun retrievedAccountTransactions(startDate: Date, response: GetTransactionsResponse) { if (response.isSuccessful) { - bankAccount.lastRetrievedTransactionsTimestamp = startDate + response.bankAccount.lastRetrievedTransactionsTimestamp = startDate - updateAccountTransactionsAndBalances(bankAccount, response) + updateAccountTransactionsAndBalances(response) } - callRetrievedAccountTransactionsResponseListener(bankAccount, response) + callRetrievedAccountTransactionsResponseListener(response) } protected open fun receivedAccountsTransactionChunk(bankAccount: BankAccount, accountTransactionsChunk: List) { if (accountTransactionsChunk.isNotEmpty()) { bankAccount.addBookedTransactions(accountTransactionsChunk) - callRetrievedAccountTransactionsResponseListener(bankAccount, GetTransactionsResponse(true, null, mapOf(bankAccount to accountTransactionsChunk))) + callRetrievedAccountTransactionsResponseListener(GetTransactionsResponse(bankAccount, true, null, accountTransactionsChunk)) } } - protected open fun updateAccountTransactionsAndBalances(bankAccount: BankAccount, response: GetTransactionsResponse) { + protected open fun updateAccountTransactionsAndBalances(response: GetTransactionsResponse) { - response.bookedTransactions.forEach { entry -> - entry.key.addBookedTransactions(entry.value) - } + val bankAccount = response.bankAccount - response.unbookedTransactions.forEach { entry -> - entry.key.addUnbookedTransactions(entry.value) - } + bankAccount.addBookedTransactions(response.bookedTransactions) - response.balances.forEach { entry -> - entry.key.balance = entry.value + bankAccount.addUnbookedTransactions(response.unbookedTransactions) + + response.balance?.let { + bankAccount.balance = it } persistAccount(bankAccount.account) // only needed because of balance - persistAccountTransactions(response.bookedTransactions, response.unbookedTransactions) + persistAccountTransactions(bankAccount, response.bookedTransactions, response.unbookedTransactions) } open fun formatAmount(amount: BigDecimal): String { @@ -356,10 +358,8 @@ open class BankingPresenter( persister.saveOrUpdateAccount(account, accounts) } - protected open fun persistAccountTransactions(bookedTransactions: Map>, unbookedTransactions: Map>) { - bookedTransactions.forEach { - persister.saveOrUpdateAccountTransactions(it.key, it.value) - } + protected open fun persistAccountTransactions(bankAccount: BankAccount, bookedTransactions: List, unbookedTransactions: List) { + persister.saveOrUpdateAccountTransactions(bankAccount, bookedTransactions) // TODO: someday also persist unbooked transactions } @@ -618,17 +618,17 @@ open class BankingPresenter( } - open fun addRetrievedAccountTransactionsResponseListener(listener: (BankAccount, GetTransactionsResponse) -> Unit): Boolean { + open fun addRetrievedAccountTransactionsResponseListener(listener: (GetTransactionsResponse) -> Unit): Boolean { return retrievedAccountTransactionsResponseListeners.add(listener) } - open fun removeRetrievedAccountTransactionsResponseListener(listener: (BankAccount, GetTransactionsResponse) -> Unit): Boolean { + open fun removeRetrievedAccountTransactionsResponseListener(listener: (GetTransactionsResponse) -> Unit): Boolean { return retrievedAccountTransactionsResponseListeners.add(listener) } - protected open fun callRetrievedAccountTransactionsResponseListener(bankAccount: BankAccount, response: GetTransactionsResponse) { + protected open fun callRetrievedAccountTransactionsResponseListener(response: GetTransactionsResponse) { ArrayList(retrievedAccountTransactionsResponseListeners).forEach { - it(bankAccount, response) // TODO: use RxJava for this + it(response) // TODO: use RxJava for this } } diff --git a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClient.kt b/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClient.kt index 85bc5756..f6551818 100644 --- a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClient.kt +++ b/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/fints4kBankingClient.kt @@ -103,7 +103,7 @@ open class fints4kBankingClient( val account = mapper.findAccountForBankAccount(customer, bankAccount) if (account == null) { - callback(GetTransactionsResponse(false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate + callback(GetTransactionsResponse(bankAccount, false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate } else { client.getTransactionsAsync(GetTransactionsParameter(parameter.alsoRetrieveBalance, parameter.fromDate, parameter.toDate, null, parameter.abortIfTanIsRequired, diff --git a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt b/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt index 098bed42..a303167d 100644 --- a/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt +++ b/ui/fints4kBankingClient/src/main/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt @@ -49,10 +49,10 @@ open class fints4kModelMapper { open fun mapResponse(bankAccount: BankAccount, response: net.dankito.banking.fints.response.client.GetTransactionsResponse): GetTransactionsResponse { - return GetTransactionsResponse(response.isSuccessful, mapErrorToShowToUser(response), - mapOf(bankAccount to mapTransactions(bankAccount, response.bookedTransactions)), - mapOf(), // TODO: map unbooked transactions - response.balance?.let { mapOf(bankAccount to it) } ?: mapOf(), + return GetTransactionsResponse(bankAccount, response.isSuccessful, mapErrorToShowToUser(response), + mapTransactions(bankAccount, response.bookedTransactions), + listOf(), // TODO: map unbooked transactions + response.balance, response.exception, response.userCancelledAction, response.tanRequiredButWeWereToldToAbortIfSo) } @@ -268,6 +268,7 @@ open class fints4kModelMapper { } open fun mapTanMedium(tanMedium: net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedium): TanMedium { + // TODO: irgendwas ging hier schief if (tanMedium is net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium) { return mapTanMedium(tanMedium) } diff --git a/ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/hbci4jBankingClient.kt b/ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/hbci4jBankingClient.kt index ec9c8c35..32c3a455 100644 --- a/ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/hbci4jBankingClient.kt +++ b/ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/hbci4jBankingClient.kt @@ -86,18 +86,14 @@ open class hbci4jBankingClient( this.account.bankAccounts = mapper.mapBankAccounts(account, accounts, passport) - val transactionsOfLast90DaysResponse = tryToRetrieveAccountTransactionsForAddedAccounts(account) - - return AddAccountResponse(true, null, account, transactionsOfLast90DaysResponse.isSuccessful, - transactionsOfLast90DaysResponse.bookedTransactions, transactionsOfLast90DaysResponse.unbookedTransactions, - transactionsOfLast90DaysResponse.balances) + return tryToRetrieveAccountTransactionsForAddedAccounts(account) } } return AddAccountResponse(false, null, account, error = connection.error) } - protected open fun tryToRetrieveAccountTransactionsForAddedAccounts(account: Account): GetTransactionsResponse { + protected open fun tryToRetrieveAccountTransactionsForAddedAccounts(account: Account): AddAccountResponse { val transactionsOfLast90DaysResponses = mutableListOf() val balances = mutableMapOf() val bookedTransactions = mutableMapOf>() @@ -108,15 +104,16 @@ open class hbci4jBankingClient( val response = getTransactionsOfLast90Days(bankAccount) transactionsOfLast90DaysResponses.add(response) - response.bookedTransactions[bankAccount]?.let { bookedTransactions.put(bankAccount, it) } - response.unbookedTransactions[bankAccount]?.let { unbookedTransactions.put(bankAccount, it) } - response.balances[bankAccount]?.let { balances.put(bankAccount, it) } + bookedTransactions.put(bankAccount, response.bookedTransactions) + unbookedTransactions.put(bankAccount, response.unbookedTransactions) + balances.put(bankAccount, response.balance ?: BigDecimal.ZERO) // TODO: really add BigDecimal.Zero if balance couldn't be retrieved? } } val supportsRetrievingTransactionsOfLast90DaysWithoutTan = transactionsOfLast90DaysResponses.firstOrNull { it.isSuccessful } != null - return GetTransactionsResponse(supportsRetrievingTransactionsOfLast90DaysWithoutTan, null, bookedTransactions, unbookedTransactions, balances) + return AddAccountResponse(true, null, account, supportsRetrievingTransactionsOfLast90DaysWithoutTan, + bookedTransactions, unbookedTransactions, balances) } @@ -162,7 +159,7 @@ open class hbci4jBankingClient( // Pruefen, ob die Kommunikation mit der Bank grundsaetzlich geklappt hat if (!status.isOK) { log.error("Could not connect to bank ${credentials.bankCode} ${status.toString()}: ${status.errorString}") - return GetTransactionsResponse(false, null, error = Exception("Could not connect to bank ${credentials.bankCode}: ${status.toString()}")) + return GetTransactionsResponse(bankAccount, false, null, error = Exception("Could not connect to bank ${credentials.bankCode}: ${status.toString()}")) } // Auswertung des Saldo-Abrufs. @@ -171,7 +168,7 @@ open class hbci4jBankingClient( val balanceResult = nullableBalanceJob.jobResult as GVRSaldoReq if(balanceResult.isOK == false) { log.error("Could not fetch balance of bank account $bankAccount: $balanceResult", balanceResult.getJobStatus().exceptions) - return GetTransactionsResponse(false, null, error = Exception("Could not fetch balance of bank account $bankAccount: $balanceResult")) + return GetTransactionsResponse(bankAccount, false, null, error = Exception("Could not fetch balance of bank account $bankAccount: $balanceResult")) } balance = balanceResult.entries[0].ready.value.bigDecimalValue @@ -185,15 +182,15 @@ open class hbci4jBankingClient( // Pruefen, ob der Abruf der Umsaetze geklappt hat if (result.isOK == false) { log.error("Could not get fetch account transactions of bank account $bankAccount: $result", result.getJobStatus().exceptions) - return GetTransactionsResponse(false, null, error = Exception("Could not fetch account transactions of bank account $bankAccount: $result")) + return GetTransactionsResponse(bankAccount, false, null, error = Exception("Could not fetch account transactions of bank account $bankAccount: $result")) } - return GetTransactionsResponse(true, null, mapOf(bankAccount to accountTransactionMapper.mapAccountTransactions(bankAccount, result)), - mapOf(), mapOf(bankAccount to balance)) + return GetTransactionsResponse(bankAccount, true, null, accountTransactionMapper.mapAccountTransactions(bankAccount, result), + listOf(), balance) } catch(e: Exception) { log.error("Could not get accounting details for bank ${credentials.bankCode}", e) - return GetTransactionsResponse(false, null, error = e) + return GetTransactionsResponse(bankAccount, false, null, error = e) } finally { closeConnection(connection) @@ -202,7 +199,7 @@ open class hbci4jBankingClient( closeConnection(connection) - return GetTransactionsResponse(false, null, error = connection.error) + return GetTransactionsResponse(bankAccount, false, null, error = connection.error) } protected open fun executeJobsForGetAccountingEntries(handle: HBCIHandler, bankAccount: BankAccount, parameter: GetTransactionsParameter): Triple {