diff --git a/README.md b/README.md index ea43134c..adb4211f 100644 --- a/README.md +++ b/README.md @@ -51,11 +51,11 @@ class ShowUsage { fun getAccountData() { - val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback()) + val client = FinTs4kBankingClient(SimpleBankingClientCallback()) - val response = client.getAccountData() + val response = client.getAccountData(bankCode, loginName, password) // that's all - printReceivedData(response) + printReceivedData(response) // now print retrieved data (save it to database, display it in UI, ...) } @@ -82,15 +82,6 @@ class ShowUsage { This fetches the booked account transactions of the last 90 days. In most cases no TAN is required for this. -In case there is, add TAN handling in Client Callback: - -```kotlin -val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback -> - val tan: String? = null // if a TAN is required, add a UI or ... - callback.invoke(EnterTanResult(tan)) // ... set a break point here, get TAN e.g. from your TAN app, set tan variable in debugger view and resume debugger -}) -``` - You can also specify options e.g. which transactions should be retrieved: ```kotlin @@ -104,10 +95,53 @@ val options = GetAccountDataOptions( val response = client.getAccountData(options) ``` +Retrieving transactions older than 90 days requires a TAN, so add TAN handling in Client Callback: + +```kotlin +val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback { tanChallenge, callback -> + val tan: String? = null // if a TAN is required, add a UI or ... + callback.invoke(EnterTanResult(tan)) // ... set a break point here, get TAN e.g. from your TAN app, set tan variable in debugger view and resume debugger +}) +``` + Add some error handling by checking `response.error`: ```kotlin response.error?.let{ error -> println("Could not fetch account data: ${error.internalError ?: error.errorMessagesFromBank.joinToString()}") } +``` + + +### Update Account Transactions + +The data model saves when it retrieved account transactions the last time (in `BankAccount.lastTransactionsRetrievalTime`). +So you only need to call `FinTs4kBankingClient.updateAccountTransactions()` to retrieve all transactions starting from +`BankAccount.lastTransactionsRetrievalTime`. + +But as we can only specify from which day on account transactions should be retrieved, response may contain some transactions +from the day of `lastTransactionsRetrievalTime` that we already have locally. To filter out these you can use +`BankingModelService().findNewTransactions(retrieveTransactions, existingTransactions)`: + +```kotlin +fun updateAccountTransactions() { + val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback()) + + // simulate account transactions we retrieved last time + val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date + val lastCallToBankServer = client.getAccountData(GetAccountDataOptions(RetrieveTransactions.AccordingToRetrieveFromAndTo, retrieveTransactionsFrom = today.minusDays(90), retrieveTransactionsTo = today.minusDays(30))) + + if (lastCallToBankServer.data != null) { // now update account transactions + val existingTransactions = lastCallToBankServer.data!!.bookedTransactions + + val updateTransactionsResponse = client.updateAccountTransactions() + + if (updateTransactionsResponse.data != null) { + val retrievedTransactions = updateTransactionsResponse.data!!.flatMap { it.bookedTransactions } + val newTransactions = BankingModelService().findNewTransactions(retrievedTransactions, existingTransactions) + // `retrievedTransactions` may contain transactions we already have locally, `newTransactions` only + // transactions that are not in `existingTransactions` + } + } +} ``` \ No newline at end of file diff --git a/SampleApp/src/main/kotlin/net/codinux/banking/client/fints4k/example/ShowUsage.kt b/SampleApp/src/main/kotlin/net/codinux/banking/client/fints4k/example/ShowUsage.kt index d19e7137..aeedf148 100644 --- a/SampleApp/src/main/kotlin/net/codinux/banking/client/fints4k/example/ShowUsage.kt +++ b/SampleApp/src/main/kotlin/net/codinux/banking/client/fints4k/example/ShowUsage.kt @@ -1,7 +1,11 @@ package net.codinux.banking.client.fints4k.example +import kotlinx.datetime.Clock import kotlinx.datetime.LocalDate +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime import net.codinux.banking.client.SimpleBankingClientCallback +import net.codinux.banking.client.fints4k.FinTs4kBankingClient import net.codinux.banking.client.fints4k.FinTs4kBankingClientForUser import net.codinux.banking.client.getAccountData import net.codinux.banking.client.model.options.GetAccountDataOptions @@ -9,6 +13,9 @@ import net.codinux.banking.client.model.options.RetrieveTransactions import net.codinux.banking.client.model.response.GetAccountDataResponse import net.codinux.banking.client.model.response.Response import net.codinux.banking.client.model.tan.EnterTanResult +import net.codinux.banking.client.service.BankingModelService +import net.codinux.banking.client.updateAccountTransactions +import net.codinux.banking.fints.extensions.minusDays fun main() { val showUsage = ShowUsage() @@ -27,11 +34,11 @@ class ShowUsage { fun getAccountDataSimpleExample() { - val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback()) + val client = FinTs4kBankingClient(SimpleBankingClientCallback()) - val response = client.getAccountData() + val response = client.getAccountData(bankCode, loginName, password) // that's all - printReceivedData(response) + printReceivedData(response) // now print retrieved data (save it to database, display it in UI, ...) } fun getAccountDataFullExample() { @@ -57,6 +64,28 @@ class ShowUsage { } + fun updateAccountTransactions() { + val client = FinTs4kBankingClientForUser(bankCode, loginName, password, SimpleBankingClientCallback()) + + // simulate account transactions we retrieved last time + val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date + val lastCallToBankServer = client.getAccountData(GetAccountDataOptions(RetrieveTransactions.AccordingToRetrieveFromAndTo, retrieveTransactionsFrom = today.minusDays(90), retrieveTransactionsTo = today.minusDays(30))) + + if (lastCallToBankServer.data != null) { // now update account transactions + val existingTransactions = lastCallToBankServer.data!!.bookedTransactions + + val updateTransactionsResponse = client.updateAccountTransactions() + + if (updateTransactionsResponse.data != null) { + val retrievedTransactions = updateTransactionsResponse.data!!.flatMap { it.bookedTransactions } + val newTransactions = BankingModelService().findNewTransactions(retrievedTransactions, existingTransactions) + // `retrievedTransactions` may contain transactions we already have locally, `newTransactions` only + // transactions that are not in `existingTransactions` + } + } + } + + private fun printReceivedData(response: Response) { response.data?.let { data -> val user = data.user