Implemented selected TAN procedure after successfully adding an account
This commit is contained in:
parent
ce3a7c564d
commit
8892368782
|
@ -11,6 +11,7 @@ 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.math.BigDecimal
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
@ -28,9 +29,11 @@ open class MainWindowPresenter(callback: FinTsClientCallback) {
|
||||||
|
|
||||||
protected val accounts = mutableMapOf<CustomerData, BankData>()
|
protected val accounts = mutableMapOf<CustomerData, BankData>()
|
||||||
|
|
||||||
protected val bookedTransactions = mutableSetOf<AccountTransaction>() // TODO: map by account
|
protected val bookedTransactions = mutableMapOf<CustomerData, MutableSet<AccountTransaction>>()
|
||||||
|
|
||||||
protected val unbookedTransactions = mutableSetOf<Any>()
|
protected val unbookedTransactions = mutableMapOf<CustomerData, MutableSet<Any>>()
|
||||||
|
|
||||||
|
protected val balances = mutableMapOf<CustomerData, BigDecimal>()
|
||||||
|
|
||||||
protected val accountAddedListeners = mutableListOf<(BankData, CustomerData) -> Unit>()
|
protected val accountAddedListeners = mutableListOf<(BankData, CustomerData) -> Unit>()
|
||||||
|
|
||||||
|
@ -45,9 +48,11 @@ open class MainWindowPresenter(callback: FinTsClientCallback) {
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
accounts.put(customer, bank)
|
accounts.put(customer, bank)
|
||||||
|
|
||||||
// TODO: show booked transactions of last 90 days in HomeFragment if available
|
|
||||||
|
|
||||||
callAccountAddedListeners(bank, customer)
|
callAccountAddedListeners(bank, customer)
|
||||||
|
|
||||||
|
if (response.supportsRetrievingTransactionsOfLast90DaysWithoutTan) {
|
||||||
|
retrievedAccountTransactions(customer, response)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(response)
|
callback(response)
|
||||||
|
@ -65,21 +70,43 @@ open class MainWindowPresenter(callback: FinTsClientCallback) {
|
||||||
callback: (GetTransactionsResponse) -> Unit) {
|
callback: (GetTransactionsResponse) -> Unit) {
|
||||||
|
|
||||||
finTsClient.getTransactionsAsync(GetTransactionsParameter(true, fromDate), bank, customer) { response ->
|
finTsClient.getTransactionsAsync(GetTransactionsParameter(true, fromDate), bank, customer) { response ->
|
||||||
if (response.isSuccessful) {
|
retrievedAccountTransactions(customer, response)
|
||||||
bookedTransactions.addAll(response.bookedTransactions) // TODO: does currently not work, overwrite equals()
|
|
||||||
unbookedTransactions.addAll(response.unbookedTransactions)
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(response) // TODO: does not return all booked transactions, only the newly retrieved ones!
|
callback(response) // TODO: does not return all booked transactions, only the newly retrieved ones!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun updateAccountsTransactionsAsync(callback: (GetTransactionsResponse) -> Unit) {
|
open fun updateAccountsTransactionsAsync(callback: (GetTransactionsResponse) -> Unit) {
|
||||||
|
accounts.forEach { entry ->
|
||||||
|
val customer = entry.key
|
||||||
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 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 lastRetrievedTransactionDate = bookedTransactions[customer]?.firstOrNull { it.bookingDate <= today }?.bookingDate
|
||||||
val fromDate = lastRetrievedTransactionDate?.let { Date(it.time - 24 * 60 * 60 * 1000) } // on day before last received transaction
|
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
|
getAccountTransactionsAsync(entry.value, customer, fromDate, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun retrievedAccountTransactions(customer: CustomerData, response: GetTransactionsResponse) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
if (bookedTransactions.containsKey(customer) == false) {
|
||||||
|
bookedTransactions.put(customer, response.bookedTransactions.toMutableSet())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bookedTransactions[customer]?.addAll(response.bookedTransactions) // TODO: does currently not work, overwrite equals()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unbookedTransactions.containsKey(customer) == false) {
|
||||||
|
unbookedTransactions.put(customer, response.unbookedTransactions.toMutableSet())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unbookedTransactions[customer]?.addAll(response.unbookedTransactions)
|
||||||
|
}
|
||||||
|
|
||||||
|
response.balance?.let {
|
||||||
|
balances[customer] = it
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,10 +132,10 @@ open class MainWindowPresenter(callback: FinTsClientCallback) {
|
||||||
val queryLowercase = query.trim().toLowerCase()
|
val queryLowercase = query.trim().toLowerCase()
|
||||||
|
|
||||||
if (queryLowercase.isEmpty()) {
|
if (queryLowercase.isEmpty()) {
|
||||||
return bookedTransactions.toList()
|
return bookedTransactions.values.flatten().toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
return bookedTransactions.filter {
|
return bookedTransactions.values.flatten().filter {
|
||||||
it.otherPartyName?.toLowerCase()?.contains(queryLowercase) == true
|
it.otherPartyName?.toLowerCase()?.contains(queryLowercase) == true
|
||||||
|| it.usage.toLowerCase().contains(queryLowercase)
|
|| it.usage.toLowerCase().contains(queryLowercase)
|
||||||
|| it.bookingText?.toLowerCase()?.contains(queryLowercase) == true
|
|| it.bookingText?.toLowerCase()?.contains(queryLowercase) == true
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package net.dankito.banking.fints4java.android.ui.adapter
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import net.dankito.banking.fints4java.android.R
|
||||||
|
import net.dankito.fints.model.TanProcedure
|
||||||
|
import net.dankito.utils.android.extensions.asActivity
|
||||||
|
import net.dankito.utils.android.ui.adapter.ListAdapter
|
||||||
|
|
||||||
|
|
||||||
|
open class TanProceduresAdapter : ListAdapter<TanProcedure>() {
|
||||||
|
|
||||||
|
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
|
||||||
|
val procedure = getItem(position)
|
||||||
|
|
||||||
|
val view = convertView ?: parent?.context?.asActivity()?.layoutInflater?.inflate(
|
||||||
|
R.layout.list_item_tan_procedure, parent, false)
|
||||||
|
|
||||||
|
view?.findViewById<TextView>(R.id.txtTanProcedureDisplayName)?.text = procedure.displayName
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package net.dankito.banking.fints4java.android.ui.dialogs
|
package net.dankito.banking.fints4java.android.ui.dialogs
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v4.app.DialogFragment
|
import android.support.v4.app.DialogFragment
|
||||||
|
@ -10,11 +11,15 @@ import android.text.TextWatcher
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.Spinner
|
||||||
|
import android.widget.TextView
|
||||||
import kotlinx.android.synthetic.main.dialog_add_account.*
|
import kotlinx.android.synthetic.main.dialog_add_account.*
|
||||||
import kotlinx.android.synthetic.main.dialog_add_account.view.*
|
import kotlinx.android.synthetic.main.dialog_add_account.view.*
|
||||||
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.BankListAdapter
|
import net.dankito.banking.fints4java.android.ui.adapter.BankListAdapter
|
||||||
|
import net.dankito.banking.fints4java.android.ui.adapter.TanProceduresAdapter
|
||||||
import net.dankito.fints.model.BankInfo
|
import net.dankito.fints.model.BankInfo
|
||||||
import net.dankito.fints.response.client.AddAccountResponse
|
import net.dankito.fints.response.client.AddAccountResponse
|
||||||
import net.dankito.utils.android.extensions.asActivity
|
import net.dankito.utils.android.extensions.asActivity
|
||||||
|
@ -91,16 +96,7 @@ open class AddAccountDialog : DialogFragment() {
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
this.dismiss()
|
this.dismiss()
|
||||||
|
|
||||||
val messageId = if (response.supportsRetrievingTransactionsOfLast90DaysWithoutTan)
|
showMessageForSuccessfullyAddedAccount(context, response)
|
||||||
R.string.dialog_add_account_message_successfully_added_account_support_retrieving_transactions_of_last_90_days_without_tan
|
|
||||||
else R.string.dialog_add_account_message_successfully_added_account
|
|
||||||
|
|
||||||
AlertDialog.Builder(context)
|
|
||||||
.setMessage(messageId)
|
|
||||||
.setPositiveButton(R.string.yes) { dialog, _ -> retrieveAccountTransactionsAndDismiss(response, dialog) }
|
|
||||||
.setNeutralButton(R.string.later) { dialog, _ -> dialog.dismiss() }
|
|
||||||
.setNegativeButton(R.string.do_not_ask_anymore) { dialog, _ -> setDoNotAskAnymoreAndDismiss(dialog) }
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AlertDialog.Builder(context)
|
AlertDialog.Builder(context)
|
||||||
|
@ -111,6 +107,47 @@ open class AddAccountDialog : DialogFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun showMessageForSuccessfullyAddedAccount(context: Context, response: AddAccountResponse) {
|
||||||
|
val view = createSuccessfullyAddedAccountView(context, response)
|
||||||
|
|
||||||
|
AlertDialog.Builder(context)
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton(R.string.yes) { dialog, _ -> retrieveAccountTransactionsAndDismiss(response, dialog) }
|
||||||
|
.setNeutralButton(R.string.later) { dialog, _ -> dialog.dismiss() }
|
||||||
|
.setNegativeButton(R.string.do_not_ask_anymore) { dialog, _ -> setDoNotAskAnymoreAndDismiss(dialog) }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun createSuccessfullyAddedAccountView(context: Context, response: AddAccountResponse): View? {
|
||||||
|
|
||||||
|
val messageId = if (response.supportsRetrievingTransactionsOfLast90DaysWithoutTan)
|
||||||
|
R.string.dialog_add_account_message_successfully_added_account_support_retrieving_transactions_of_last_90_days_without_tan
|
||||||
|
else R.string.dialog_add_account_message_successfully_added_account
|
||||||
|
|
||||||
|
val view = context.asActivity()?.layoutInflater?.inflate(R.layout.view_successfully_added_account, null)
|
||||||
|
|
||||||
|
val adapter = TanProceduresAdapter()
|
||||||
|
adapter.setItems(response.customer.supportedTanProcedures)
|
||||||
|
|
||||||
|
view?.findViewById<TextView>(R.id.txtSuccessfullyAddedAccountMessage)?.setText(messageId)
|
||||||
|
|
||||||
|
view?.findViewById<Spinner>(R.id.spnTanProcedures)?.let { spinner ->
|
||||||
|
spinner.adapter = adapter
|
||||||
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
|
response.customer.selectedTanProcedure = adapter.getItem(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
spinner.setSelection(adapter.getItems().indexOfFirst { it.displayName.contains("manuell", true) == false })
|
||||||
|
}
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun retrieveAccountTransactionsAndDismiss(response: AddAccountResponse, messageDialog: DialogInterface) {
|
protected open fun retrieveAccountTransactionsAndDismiss(response: AddAccountResponse, messageDialog: DialogInterface) {
|
||||||
presenter.getAccountTransactionsAsync(response.bank, response.customer) { } // TODO: show error message if not successful. Here or in HomeFragment
|
presenter.getAccountTransactionsAsync(response.bank, response.customer) { } // TODO: show error message if not successful. Here or in HomeFragment
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/txtTanProcedureDisplayName"
|
||||||
|
style="@style/TextAppearance.AppCompat.Medium"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
/>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="@dimen/view_successfully_added_account_padding"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtSuccessfullyAddedAccountMessage"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/view_successfully_added_account_message_margin_bottom"
|
||||||
|
style="@style/TextAppearance.AppCompat.Medium"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/view_successfully_added_account_tan_procedures_height"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spnTanProcedures"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -29,6 +29,10 @@
|
||||||
<dimen name="list_item_bank_info_bank_code_and_address_height">30dp</dimen>
|
<dimen name="list_item_bank_info_bank_code_and_address_height">30dp</dimen>
|
||||||
<dimen name="list_item_bank_info_bank_code_width">80dp</dimen>
|
<dimen name="list_item_bank_info_bank_code_width">80dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="view_successfully_added_account_padding">12dp</dimen>
|
||||||
|
<dimen name="view_successfully_added_account_message_margin_bottom">12dp</dimen>
|
||||||
|
<dimen name="view_successfully_added_account_tan_procedures_height">40dp</dimen>
|
||||||
|
|
||||||
<dimen name="dialog_bank_transfer_padding">4dp</dimen>
|
<dimen name="dialog_bank_transfer_padding">4dp</dimen>
|
||||||
<dimen name="dialog_bank_transfer_input_fields_height">40dp</dimen>
|
<dimen name="dialog_bank_transfer_input_fields_height">40dp</dimen>
|
||||||
<dimen name="dialog_bank_transfer_autocomplete_fields_height">50dp</dimen>
|
<dimen name="dialog_bank_transfer_autocomplete_fields_height">50dp</dimen>
|
||||||
|
|
|
@ -12,8 +12,8 @@ open class AddAccountResponse(
|
||||||
val bank: BankData,
|
val bank: BankData,
|
||||||
val customer: CustomerData,
|
val customer: CustomerData,
|
||||||
val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false,
|
val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false,
|
||||||
val bookedTransactionsOfLast90Days: List<AccountTransaction> = listOf(),
|
bookedTransactionsOfLast90Days: List<AccountTransaction> = listOf(),
|
||||||
val unbookedTransactionsOfLast90Days: List<Any> = listOf(),
|
unbookedTransactionsOfLast90Days: List<Any> = listOf(),
|
||||||
val balance: BigDecimal? = null
|
balance: BigDecimal? = null
|
||||||
)
|
)
|
||||||
: FinTsClientResponse(response)
|
: GetTransactionsResponse(response, bookedTransactionsOfLast90Days, unbookedTransactionsOfLast90Days, balance)
|
Loading…
Reference in New Issue