Implemented updating account transactions

This commit is contained in:
dankl 2019-10-27 21:56:46 +01:00 committed by dankito
parent 5388d3ee62
commit 234def482a
4 changed files with 84 additions and 15 deletions

View File

@ -10,6 +10,8 @@ import net.dankito.fints.response.client.FinTsClientResponse
import net.dankito.fints.response.client.GetTransactionsResponse import net.dankito.fints.response.client.GetTransactionsResponse
import net.dankito.utils.IThreadPool import net.dankito.utils.IThreadPool
import net.dankito.utils.ThreadPool import net.dankito.utils.ThreadPool
import java.util.*
import kotlin.collections.ArrayList
open class MainWindowPresenter(callback: FinTsClientCallback) { open class MainWindowPresenter(callback: FinTsClientCallback) {
@ -23,6 +25,8 @@ open class MainWindowPresenter(callback: FinTsClientCallback) {
protected val bankDataMapper = BankDataMapper() protected val bankDataMapper = BankDataMapper()
protected val accounts = mutableMapOf<CustomerData, BankData>()
protected val bookedTransactions = mutableSetOf<AccountTransaction>() // TODO: map by account protected val bookedTransactions = mutableSetOf<AccountTransaction>() // TODO: map by account
protected val unbookedTransactions = mutableSetOf<Any>() protected val unbookedTransactions = mutableSetOf<Any>()
@ -38,6 +42,8 @@ open class MainWindowPresenter(callback: FinTsClientCallback) {
finTsClient.checkIfAccountExistsAsync(bank, customer) { response -> finTsClient.checkIfAccountExistsAsync(bank, customer) { response ->
if (response.isSuccessful) { if (response.isSuccessful) {
accounts.put(customer, bank)
callAccountAddedListeners(bank, customer) callAccountAddedListeners(bank, customer)
} }
@ -49,16 +55,30 @@ open class MainWindowPresenter(callback: FinTsClientCallback) {
open fun getAccountTransactionsAsync(bank: BankData, customer: CustomerData, open fun getAccountTransactionsAsync(bank: BankData, customer: CustomerData,
callback: (GetTransactionsResponse) -> Unit) { callback: (GetTransactionsResponse) -> Unit) {
finTsClient.getTransactionsAsync(GetTransactionsParameter(), bank, customer) { response -> getAccountTransactionsAsync(bank, customer, null, callback)
}
open fun getAccountTransactionsAsync(bank: BankData, customer: CustomerData, fromDate: Date?,
callback: (GetTransactionsResponse) -> Unit) {
finTsClient.getTransactionsAsync(GetTransactionsParameter(true, fromDate), bank, customer) { response ->
if (response.isSuccessful) { if (response.isSuccessful) {
bookedTransactions.addAll(response.bookedTransactions) bookedTransactions.addAll(response.bookedTransactions) // TODO: does currently not work, overwrite equals()
unbookedTransactions.addAll(response.unbookedTransactions) unbookedTransactions.addAll(response.unbookedTransactions)
} }
callback(response) callback(response) // TODO: does not return all booked transactions, only the newly retrieved ones!
} }
} }
open fun updateAccountsTransactionsAsync(callback: (GetTransactionsResponse) -> Unit) {
val today = Date() // TODO: still don't know where this bug is coming from that bank returns a transaction dated at end of year
val lastRetrievedTransactionDate = bookedTransactions.firstOrNull { it.bookingDate <= today }?.bookingDate // TODO: make multi-account ready; currently if don't differentiate booked transactions by accounts
val fromDate = lastRetrievedTransactionDate?.let { Date(it.time - 24 * 60 * 60 * 1000) } // on day before last received transaction
accounts.forEach { entry -> getAccountTransactionsAsync(entry.value, entry.key, fromDate, callback) } // TODO: this is not a good solution for multiple accounts
}
open fun searchForBankAsync(enteredBankCode: String, callback: (List<BankInfo>) -> Unit) { open fun searchForBankAsync(enteredBankCode: String, callback: (List<BankInfo>) -> Unit) {
threadPool.runAsync { threadPool.runAsync {

View File

@ -5,6 +5,8 @@ import android.arch.lifecycle.ViewModelProviders
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.support.v7.widget.SearchView import android.support.v7.widget.SearchView
@ -15,25 +17,26 @@ import net.dankito.banking.fints4java.android.MainActivity
import net.dankito.banking.fints4java.android.R import net.dankito.banking.fints4java.android.R
import net.dankito.banking.fints4java.android.ui.MainWindowPresenter import net.dankito.banking.fints4java.android.ui.MainWindowPresenter
import net.dankito.banking.fints4java.android.ui.adapter.AccountTransactionAdapter import net.dankito.banking.fints4java.android.ui.adapter.AccountTransactionAdapter
import net.dankito.banking.fints4java.android.ui.dialogs.BankTransferDialog
import net.dankito.fints.model.BankData import net.dankito.fints.model.BankData
import net.dankito.fints.model.BankTransferData
import net.dankito.fints.model.CustomerData import net.dankito.fints.model.CustomerData
import net.dankito.fints.response.client.GetTransactionsResponse
import net.dankito.utils.android.extensions.asActivity import net.dankito.utils.android.extensions.asActivity
import org.slf4j.LoggerFactory import java.math.BigDecimal
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
companion object {
private val log = LoggerFactory.getLogger(HomeFragment::class.java)
}
private lateinit var homeViewModel: HomeViewModel private lateinit var homeViewModel: HomeViewModel
private lateinit var mnitmBalance: MenuItem private lateinit var mnitmBalance: MenuItem
private lateinit var mnitmSearchTransactions: MenuItem private lateinit var mnitmSearchTransactions: MenuItem
private lateinit var mnitmUpdateTransactions: MenuItem
private val transactionAdapter = AccountTransactionAdapter() private val transactionAdapter = AccountTransactionAdapter()
@ -77,12 +80,24 @@ class HomeFragment : Fragment() {
mnitmBalance = menu.findItem(R.id.mnitmBalance) mnitmBalance = menu.findItem(R.id.mnitmBalance)
mnitmSearchTransactions = menu.findItem(R.id.mnitmSearchTransactions) mnitmSearchTransactions = menu.findItem(R.id.mnitmSearchTransactions)
mnitmUpdateTransactions = menu.findItem(R.id.mnitmUpdateTransactions)
initSearchView() initSearchView()
} }
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.mnitmUpdateTransactions -> {
updateAccountsTransactions()
return true
}
}
return super.onOptionsItemSelected(item)
}
private fun initSearchView() { private fun initSearchView() {
context?.asActivity()?.let { context -> context?.asActivity()?.let { context ->
(context.getSystemService(Context.SEARCH_SERVICE) as? SearchManager)?.let { searchManager -> (context.getSystemService(Context.SEARCH_SERVICE) as? SearchManager)?.let { searchManager ->
@ -115,16 +130,34 @@ class HomeFragment : Fragment() {
private fun retrieveAccountTransactions(bank: BankData, customer: CustomerData) { private fun retrieveAccountTransactions(bank: BankData, customer: CustomerData) {
presenter.getAccountTransactionsAsync(bank, customer) { response -> presenter.getAccountTransactionsAsync(bank, customer) { response ->
context?.asActivity()?.runOnUiThread { handleGetTransactionsResponse(response)
}
}
private fun updateAccountsTransactions() {
presenter.updateAccountsTransactionsAsync { response ->
handleGetTransactionsResponse(response)
}
}
private fun handleGetTransactionsResponse(response: GetTransactionsResponse) {
context?.asActivity()?.let { activity ->
activity.runOnUiThread {
if (response.isSuccessful) { if (response.isSuccessful) {
transactionAdapter.items = response.bookedTransactions transactionAdapter.items = response.bookedTransactions
mnitmSearchTransactions.isVisible = response.bookedTransactions.isNotEmpty()
mnitmUpdateTransactions.isVisible = response.bookedTransactions.isNotEmpty()
response.balance?.let { response.balance?.let {
mnitmBalance.title = it.toString() mnitmBalance.title = it.toString()
mnitmBalance.setVisible(true)
} }
} } else {
else { AlertDialog.Builder(activity)
// TODO: show error .setMessage(activity.getString(R.string.fragment_home_could_not_retrieve_account_transactions, response.exception ?: response.errorsToShowToUser.joinToString("\n")))
.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
.show()
} }
} }
} }

View File

@ -5,14 +5,26 @@
<item android:id="@+id/mnitmSearchTransactions" <item android:id="@+id/mnitmSearchTransactions"
android:icon="@android:drawable/ic_menu_search" android:icon="@android:drawable/ic_menu_search"
android:title="@string/search"
app:showAsAction="always|collapseActionView" app:showAsAction="always|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" app:actionViewClass="android.support.v7.widget.SearchView"
android:title="@string/search" android:orderInCategory="10"
android:visible="false"
/>
<item android:id="@+id/mnitmUpdateTransactions"
android:icon="@android:drawable/stat_notify_sync"
android:title="@string/menu_main_update_transactions"
app:showAsAction="always"
android:orderInCategory="200"
android:visible="false"
/> />
<item android:id="@+id/mnitmBalance" <item android:id="@+id/mnitmBalance"
android:title="" android:title=""
app:showAsAction="always" app:showAsAction="always"
android:orderInCategory="500"
android:visible="false"
/> />
</menu> </menu>

View File

@ -14,6 +14,10 @@
<string name="menu_home">Home</string> <string name="menu_home">Home</string>
<string name="menu_main_update_transactions">Update transactions</string>
<string name="fragment_home_could_not_retrieve_account_transactions">Could not retrieve account transactions:\n%s</string>
<string name="dialog_add_account_enter_bank_code">Bank code:</string> <string name="dialog_add_account_enter_bank_code">Bank code:</string>
<string name="dialog_add_account_enter_fints_server_address">FinTS server address:</string> <string name="dialog_add_account_enter_fints_server_address">FinTS server address:</string>
<string name="dialog_add_account_enter_customer_id">Customer Id:</string> <string name="dialog_add_account_enter_customer_id">Customer Id:</string>