Renamed Account to Customer

This commit is contained in:
dankito 2020-06-14 23:15:52 +02:00
parent 9a5e0a1098
commit b5cb401636
31 changed files with 194 additions and 194 deletions

View File

@ -13,7 +13,7 @@ import net.dankito.banking.LuceneConfig.Companion.OtherPartyAccountIdFieldName
import net.dankito.banking.LuceneConfig.Companion.OtherPartyBankCodeFieldName import net.dankito.banking.LuceneConfig.Companion.OtherPartyBankCodeFieldName
import net.dankito.banking.LuceneConfig.Companion.OtherPartyNameFieldName import net.dankito.banking.LuceneConfig.Companion.OtherPartyNameFieldName
import net.dankito.banking.LuceneConfig.Companion.UsageFieldName import net.dankito.banking.LuceneConfig.Companion.UsageFieldName
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.utils.lucene.index.DocumentsWriter import net.dankito.utils.lucene.index.DocumentsWriter
@ -79,14 +79,14 @@ open class LuceneBankingPersistence(
} }
override fun deleteAccount(account: Account, allAccounts: List<Account>) { override fun deleteAccount(customer: Customer, allCustomers: List<Customer>) {
try { try {
deleteAccountTransactions(account.bankAccounts) deleteAccountTransactions(customer.bankAccounts)
} catch (e: Exception) { } catch (e: Exception) {
log.error("Could not delete account transactions of account $account", e) log.error("Could not delete account transactions of account $customer", e)
} }
super.deleteAccount(account, allAccounts) super.deleteAccount(customer, allCustomers)
} }
protected open fun deleteAccountTransactions(bankAccounts: List<BankAccount>) { protected open fun deleteAccountTransactions(bankAccounts: List<BankAccount>) {

View File

@ -1,7 +1,7 @@
package net.dankito.banking.search package net.dankito.banking.search
import net.dankito.banking.persistence.LuceneBankingPersistence import net.dankito.banking.persistence.LuceneBankingPersistence
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.utils.io.FileUtils import net.dankito.utils.io.FileUtils
@ -35,7 +35,7 @@ class LuceneRemitteeSearcherTest {
private val Amount = BigDecimal.valueOf(123.45) private val Amount = BigDecimal.valueOf(123.45)
private val bankAccountMock = BankAccount(mock(Account::class.java), "", "", null, null) private val bankAccountMock = BankAccount(mock(Customer::class.java), "", "", null, null)
private val dateFormat = SimpleDateFormat("dd.MM.yyyy") private val dateFormat = SimpleDateFormat("dd.MM.yyyy")

View File

@ -1,6 +1,6 @@
package net.dankito.banking.persistence package net.dankito.banking.persistence
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.utils.serialization.ISerializer import net.dankito.utils.serialization.ISerializer
@ -19,16 +19,16 @@ open class BankingPersistenceJson(
} }
override fun saveOrUpdateAccount(account: Account, allAccounts: List<Account>) { override fun saveOrUpdateAccount(customer: Customer, allCustomers: List<Customer>) {
serializer.serializeObject(allAccounts, jsonFile) serializer.serializeObject(allCustomers, jsonFile)
} }
override fun deleteAccount(account: Account, allAccounts: List<Account>) { override fun deleteAccount(customer: Customer, allCustomers: List<Customer>) {
serializer.serializeObject(allAccounts, jsonFile) serializer.serializeObject(allCustomers, jsonFile)
} }
override fun readPersistedAccounts(): List<Account> { override fun readPersistedAccounts(): List<Customer> {
return serializer.deserializeListOr(jsonFile, Account::class.java, listOf()) return serializer.deserializeListOr(jsonFile, Customer::class.java, listOf())
} }

View File

@ -3,7 +3,7 @@ package net.dankito.banking.ui.android
import net.dankito.banking.ui.android.util.CurrentActivityTracker import net.dankito.banking.ui.android.util.CurrentActivityTracker
import net.dankito.banking.ui.IRouter import net.dankito.banking.ui.IRouter
import net.dankito.banking.ui.android.dialogs.* import net.dankito.banking.ui.android.dialogs.*
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.parameters.TransferMoneyData import net.dankito.banking.ui.model.parameters.TransferMoneyData
import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult
@ -23,13 +23,13 @@ open class RouterAndroid(protected val activityTracker: CurrentActivityTracker)
} }
} }
override fun getTanFromUserFromNonUiThread(account: Account, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult { override fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult {
val enteredTan = AtomicReference<EnterTanResult>(null) val enteredTan = AtomicReference<EnterTanResult>(null)
val tanEnteredLatch = CountDownLatch(1) val tanEnteredLatch = CountDownLatch(1)
activityTracker.currentOrNextActivity { activity -> activityTracker.currentOrNextActivity { activity ->
activity.runOnUiThread { activity.runOnUiThread {
EnterTanDialog().show(account, tanChallenge, activity, false) { EnterTanDialog().show(customer, tanChallenge, activity, false) {
enteredTan.set(it) enteredTan.set(it)
tanEnteredLatch.countDown() tanEnteredLatch.countDown()
} }

View File

@ -51,7 +51,7 @@ open class AccountTransactionAdapter(protected val presenter: BankingPresenter)
viewHolder.txtvwAmount.text = presenter.formatAmount(item.amount) viewHolder.txtvwAmount.text = presenter.formatAmount(item.amount)
viewHolder.txtvwAmount.setTextColorToColorResource(if (item.amount >= BigDecimal.ZERO) R.color.positiveAmount else R.color.negativeAmount) viewHolder.txtvwAmount.setTextColorToColorResource(if (item.amount >= BigDecimal.ZERO) R.color.positiveAmount else R.color.negativeAmount)
val iconUrl = item.bankAccount.account.bank.iconUrl val iconUrl = item.bankAccount.customer.bank.iconUrl
if (iconUrl != null && presenter.areAllAccountSelected) { if (iconUrl != null && presenter.areAllAccountSelected) {
viewHolder.imgvwBankIcon.visibility = View.VISIBLE viewHolder.imgvwBankIcon.visibility = View.VISIBLE
viewHolder.imgvwBankIcon.setImageURI(Uri.parse(iconUrl)) viewHolder.imgvwBankIcon.setImageURI(Uri.parse(iconUrl))

View File

@ -32,7 +32,7 @@ open class BankAccountsAdapter(bankAccounts: List<BankAccount>) : ListAdapter<Ba
protected open fun setIcon(bankAccount: BankAccount, imgBankIcon: ImageView) { protected open fun setIcon(bankAccount: BankAccount, imgBankIcon: ImageView) {
try { try {
val iconUrl = bankAccount.account.bank.iconUrl val iconUrl = bankAccount.customer.bank.iconUrl
imgBankIcon.visibility = if (iconUrl == null) View.GONE else View.VISIBLE imgBankIcon.visibility = if (iconUrl == null) View.GONE else View.VISIBLE
imgBankIcon.setImageURI(Uri.parse(iconUrl)) imgBankIcon.setImageURI(Uri.parse(iconUrl))
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -169,7 +169,7 @@ open class AddAccountDialog : DialogFragment() {
} }
protected open fun retrieveAccountTransactionsAndDismiss(response: AddAccountResponse, messageDialog: DialogInterface) { protected open fun retrieveAccountTransactionsAndDismiss(response: AddAccountResponse, messageDialog: DialogInterface) {
presenter.fetchAccountTransactionsAsync(response.account) { } presenter.fetchAccountTransactionsAsync(response.customer) { }
messageDialog.dismiss() messageDialog.dismiss()
} }

View File

@ -20,7 +20,7 @@ import net.dankito.banking.ui.android.di.BankingComponent
import net.dankito.banking.ui.android.adapter.TanMediumAdapter import net.dankito.banking.ui.android.adapter.TanMediumAdapter
import net.dankito.banking.ui.android.adapter.TanProceduresAdapter import net.dankito.banking.ui.android.adapter.TanProceduresAdapter
import net.dankito.banking.ui.android.listener.ListItemSelectedListener import net.dankito.banking.ui.android.listener.ListItemSelectedListener
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.responses.BankingClientResponse import net.dankito.banking.ui.model.responses.BankingClientResponse
import net.dankito.banking.ui.model.tan.* import net.dankito.banking.ui.model.tan.*
import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.banking.ui.presenter.BankingPresenter
@ -40,7 +40,7 @@ open class EnterTanDialog : DialogFragment() {
} }
protected lateinit var account: Account protected lateinit var customer: Customer
protected lateinit var tanChallenge: TanChallenge protected lateinit var tanChallenge: TanChallenge
@ -58,10 +58,10 @@ open class EnterTanDialog : DialogFragment() {
} }
open fun show(account: Account, tanChallenge: TanChallenge, activity: AppCompatActivity, open fun show(customer: Customer, tanChallenge: TanChallenge, activity: AppCompatActivity,
fullscreen: Boolean = false, tanEnteredCallback: (EnterTanResult) -> Unit) { fullscreen: Boolean = false, tanEnteredCallback: (EnterTanResult) -> Unit) {
this.account = account this.customer = customer
this.tanChallenge = tanChallenge this.tanChallenge = tanChallenge
this.tanEnteredCallback = tanEnteredCallback this.tanEnteredCallback = tanEnteredCallback
@ -95,13 +95,13 @@ open class EnterTanDialog : DialogFragment() {
protected open fun setupSelectTanProcedureView(rootView: View) { protected open fun setupSelectTanProcedureView(rootView: View) {
val adapter = TanProceduresAdapter() val adapter = TanProceduresAdapter()
val tanProceduresWithoutUnsupported = account.supportedTanProcedures.filterNot { it.type == TanProcedureType.ChipTanUsb } // USB tan generators are not supported on Android val tanProceduresWithoutUnsupported = customer.supportedTanProcedures.filterNot { it.type == TanProcedureType.ChipTanUsb } // USB tan generators are not supported on Android
adapter.setItems(tanProceduresWithoutUnsupported) adapter.setItems(tanProceduresWithoutUnsupported)
rootView.findViewById<Spinner>(R.id.spnTanProcedures)?.let { spinner -> rootView.findViewById<Spinner>(R.id.spnTanProcedures)?.let { spinner ->
spinner.adapter = adapter spinner.adapter = adapter
val selectedTanProcedure = account.selectedTanProcedure val selectedTanProcedure = customer.selectedTanProcedure
?: tanProceduresWithoutUnsupported.firstOrNull { it.type != TanProcedureType.ChipTanManuell && it.type != TanProcedureType.ChipTanUsb } ?: tanProceduresWithoutUnsupported.firstOrNull { it.type != TanProcedureType.ChipTanManuell && it.type != TanProcedureType.ChipTanUsb }
?: tanProceduresWithoutUnsupported.firstOrNull() ?: tanProceduresWithoutUnsupported.firstOrNull()
selectedTanProcedure?.let { spinner.setSelection(adapter.getItems().indexOf(selectedTanProcedure)) } selectedTanProcedure?.let { spinner.setSelection(adapter.getItems().indexOf(selectedTanProcedure)) }
@ -120,7 +120,7 @@ open class EnterTanDialog : DialogFragment() {
protected open fun setupSelectTanMediumView(rootView: View) { protected open fun setupSelectTanMediumView(rootView: View) {
rootView.lytTanMedium.visibility = View.VISIBLE rootView.lytTanMedium.visibility = View.VISIBLE
tanMediumAdapter.setItems(account.tanMediaSorted) tanMediumAdapter.setItems(customer.tanMediaSorted)
rootView.spnTanMedium.adapter = tanMediumAdapter rootView.spnTanMedium.adapter = tanMediumAdapter
rootView.spnTanMedium.onItemSelectedListener = ListItemSelectedListener(tanMediumAdapter) { selectedTanMedium -> rootView.spnTanMedium.onItemSelectedListener = ListItemSelectedListener(tanMediumAdapter) { selectedTanMedium ->
@ -140,7 +140,7 @@ open class EnterTanDialog : DialogFragment() {
protected open fun setupTanView(rootView: View) { protected open fun setupTanView(rootView: View) {
if (OpticalTanProcedures.contains(tanChallenge.tanProcedure.type)) { if (OpticalTanProcedures.contains(tanChallenge.tanProcedure.type)) {
if (account.tanMedia.isNotEmpty()) { if (customer.tanMedia.isNotEmpty()) {
setupSelectTanMediumView(rootView) setupSelectTanMediumView(rootView)
} }

View File

@ -51,7 +51,7 @@ open class SendMessageLogDialog : DialogFragment() {
} }
protected open fun setupUI(rootView: View) { protected open fun setupUI(rootView: View) {
val messageLog = presenter.getMessageLogForAccounts(presenter.accounts).joinToString("\r\n\r\n") val messageLog = presenter.getMessageLogForAccounts(presenter.customers).joinToString("\r\n\r\n")
if (messageLog.isBlank()) { if (messageLog.isBlank()) {
rootView.txtvwInfoNoMessageLogEntriesYet.visibility = View.VISIBLE rootView.txtvwInfoNoMessageLogEntriesYet.visibility = View.VISIBLE

View File

@ -20,7 +20,7 @@ import com.mikepenz.materialdrawer.util.removeItemByPosition
import com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView import com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView
import net.dankito.banking.ui.android.R import net.dankito.banking.ui.android.R
import net.dankito.banking.ui.android.extensions.withIcon import net.dankito.banking.ui.android.extensions.withIcon
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.banking.ui.presenter.BankingPresenter
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -129,7 +129,7 @@ open class DrawerView(
} }
private fun createAccountsDrawerItems(): List<IDrawerItem<*>> { private fun createAccountsDrawerItems(): List<IDrawerItem<*>> {
return presenter.accounts.map { account -> return presenter.customers.map { account ->
val accountItem = createAccountDrawerItem(account) val accountItem = createAccountDrawerItem(account)
val bankAccountsItems = createBankAccountsDrawerItems(account).toMutableList() val bankAccountsItems = createBankAccountsDrawerItems(account).toMutableList()
@ -139,20 +139,20 @@ open class DrawerView(
}.flatten() }.flatten()
} }
private fun createAccountDrawerItem(account: Account): IDrawerItem<*> { private fun createAccountDrawerItem(customer: Customer): IDrawerItem<*> {
val accountItem = AccountDrawerItem() val accountItem = AccountDrawerItem()
.withName(account.displayName) .withName(customer.displayName)
.withLevel(AccountLevel) .withLevel(AccountLevel)
// .withSecondaryIcon(GoogleMaterial.Icon.gmd_settings) // used when editing account is implemented // .withSecondaryIcon(GoogleMaterial.Icon.gmd_settings) // used when editing account is implemented
.withSecondaryIcon(GoogleMaterial.Icon.gmd_delete) .withSecondaryIcon(GoogleMaterial.Icon.gmd_delete)
.withSecondaryIconColor(activity, R.color.primaryTextColor_Dark) .withSecondaryIconColor(activity, R.color.primaryTextColor_Dark)
.withOnSecondaryIconClickedListener { closeDrawerAndEditAccount(account) } .withOnSecondaryIconClickedListener { closeDrawerAndEditAccount(customer) }
.withIcon(account.bank.iconUrl ?: "") .withIcon(customer.bank.iconUrl ?: "")
.withSelected(presenter.isSingleSelectedAccount(account)) .withSelected(presenter.isSingleSelectedAccount(customer))
.withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedAccount(account) } } .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedAccount(customer) } }
if (account.bank.iconUrl == null) { if (customer.bank.iconUrl == null) {
accountItem.withIcon(activity, FontAwesome.Icon.faw_piggy_bank, R.color.primaryTextColor_Dark) accountItem.withIcon(activity, FontAwesome.Icon.faw_piggy_bank, R.color.primaryTextColor_Dark)
} }
@ -160,8 +160,8 @@ open class DrawerView(
return accountItem return accountItem
} }
private fun createBankAccountsDrawerItems(account: Account): List<IDrawerItem<*>> { private fun createBankAccountsDrawerItems(customer: Customer): List<IDrawerItem<*>> {
return account.bankAccounts.map { bankAccount -> return customer.bankAccounts.map { bankAccount ->
SecondaryDrawerItem() SecondaryDrawerItem()
.withName(bankAccount.displayName) .withName(bankAccount.displayName)
.withLevel(BankAccountLevel) .withLevel(BankAccountLevel)
@ -176,20 +176,20 @@ open class DrawerView(
return false return false
} }
private fun closeDrawerAndEditAccount(account: Account) { private fun closeDrawerAndEditAccount(customer: Customer) {
closeDrawer() closeDrawer()
editAccount(account) editAccount(customer)
} }
private fun editAccount(account: Account) { private fun editAccount(customer: Customer) {
// TODO: implement editing account (e.g. displayed name etc.) // TODO: implement editing account (e.g. displayed name etc.)
AlertDialog.Builder(activity) AlertDialog.Builder(activity)
.setMessage(activity.getString(R.string.dialog_edit_account_ask_should_account_be_deleted, account.displayName)) .setMessage(activity.getString(R.string.dialog_edit_account_ask_should_account_be_deleted, customer.displayName))
.setPositiveButton(R.string.delete) { dialog, _ -> .setPositiveButton(R.string.delete) { dialog, _ ->
dialog.dismiss() dialog.dismiss()
presenter.deleteAccount(account) presenter.deleteAccount(customer)
} }
.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() } .setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
.show() .show()

View File

@ -4,7 +4,7 @@ import net.dankito.banking.ui.IRouter
import net.dankito.banking.ui.javafx.dialogs.AddAccountDialog import net.dankito.banking.ui.javafx.dialogs.AddAccountDialog
import net.dankito.banking.ui.javafx.dialogs.cashtransfer.TransferMoneyDialog import net.dankito.banking.ui.javafx.dialogs.cashtransfer.TransferMoneyDialog
import net.dankito.banking.ui.javafx.dialogs.tan.EnterTanDialog import net.dankito.banking.ui.javafx.dialogs.tan.EnterTanDialog
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.parameters.TransferMoneyData import net.dankito.banking.ui.model.parameters.TransferMoneyData
import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult
@ -25,12 +25,12 @@ open class RouterJavaFx : IRouter {
AddAccountDialog(presenter).show(messages["add.account.dialog.title"]) AddAccountDialog(presenter).show(messages["add.account.dialog.title"])
} }
override fun getTanFromUserFromNonUiThread(account: Account, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult { override fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult {
val enteredTan = AtomicReference<EnterTanResult>(null) val enteredTan = AtomicReference<EnterTanResult>(null)
val tanEnteredLatch = CountDownLatch(1) val tanEnteredLatch = CountDownLatch(1)
FX.runAndWait { FX.runAndWait {
EnterTanDialog(account, tanChallenge, presenter) { EnterTanDialog(customer, tanChallenge, presenter) {
enteredTan.set(it) enteredTan.set(it)
tanEnteredLatch.countDown() tanEnteredLatch.countDown()
}.show(messages["enter.tan.dialog.title"]) }.show(messages["enter.tan.dialog.title"])

View File

@ -10,14 +10,14 @@ import javafx.scene.input.KeyCode
import net.dankito.banking.ui.javafx.dialogs.JavaFxDialogService import net.dankito.banking.ui.javafx.dialogs.JavaFxDialogService
import net.dankito.banking.ui.javafx.model.AccountsAccountTreeItem import net.dankito.banking.ui.javafx.model.AccountsAccountTreeItem
import net.dankito.banking.ui.javafx.model.AccountsRootTreeItem import net.dankito.banking.ui.javafx.model.AccountsRootTreeItem
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.banking.ui.presenter.BankingPresenter
import tornadofx.* import tornadofx.*
import tornadofx.FX.Companion.messages import tornadofx.FX.Companion.messages
open class AccountsTreeView(accounts: ObservableList<Account>, protected val presenter: BankingPresenter) open class AccountsTreeView(customers: ObservableList<Customer>, protected val presenter: BankingPresenter)
: TreeView<String>(AccountsRootTreeItem(accounts)) { : TreeView<String>(AccountsRootTreeItem(customers)) {
protected var currentMenu: ContextMenu? = null protected var currentMenu: ContextMenu? = null
@ -64,7 +64,7 @@ open class AccountsTreeView(accounts: ObservableList<Account>, protected val pre
} }
protected open fun askIfAccountShouldBeDeleted(treeItem: AccountsAccountTreeItem) { protected open fun askIfAccountShouldBeDeleted(treeItem: AccountsAccountTreeItem) {
val account = treeItem.account val account = treeItem.customer
val selectedButton = JavaFxDialogService().showDialog( val selectedButton = JavaFxDialogService().showDialog(
Alert.AlertType.WARNING, Alert.AlertType.WARNING,

View File

@ -15,7 +15,7 @@ import tornadofx.*
open class AccountsView(protected val presenter: BankingPresenter) : View() { open class AccountsView(protected val presenter: BankingPresenter) : View() {
protected val accounts = FXCollections.observableArrayList(presenter.accounts) protected val accounts = FXCollections.observableArrayList(presenter.customers)
init { init {
@ -70,7 +70,7 @@ open class AccountsView(protected val presenter: BankingPresenter) : View() {
accountTreeItem?.let { accountTreeItem?.let {
when (accountTreeItem) { when (accountTreeItem) {
is AccountsBankAccountTreeItem -> presenter.selectedBankAccount(accountTreeItem.bankAccount) is AccountsBankAccountTreeItem -> presenter.selectedBankAccount(accountTreeItem.bankAccount)
is AccountsAccountTreeItem -> presenter.selectedAccount(accountTreeItem.account) is AccountsAccountTreeItem -> presenter.selectedAccount(accountTreeItem.customer)
else -> presenter.selectedAllBankAccounts() else -> presenter.selectedAllBankAccounts()
} }
} }

View File

@ -254,7 +254,7 @@ open class AddAccountDialog(protected val presenter: BankingPresenter) : Window(
handleSuccessfullyAddedAccountResultOnUiThread(response) handleSuccessfullyAddedAccountResultOnUiThread(response)
} }
else { else {
val account = response.account val account = response.customer
checkEnteredCredentialsResult.value = String.format(messages["add.account.dialog.error.could.not.add.account"], checkEnteredCredentialsResult.value = String.format(messages["add.account.dialog.error.could.not.add.account"],
account.bank.bankCode, account.customerId, response.errorToShowToUser) account.bank.bankCode, account.customerId, response.errorToShowToUser)
@ -270,7 +270,7 @@ open class AddAccountDialog(protected val presenter: BankingPresenter) : Window(
val userSelection = dialogService.showDialog(Alert.AlertType.CONFIRMATION, message, null, currentStage, ButtonType.YES, ButtonType.NO) val userSelection = dialogService.showDialog(Alert.AlertType.CONFIRMATION, message, null, currentStage, ButtonType.YES, ButtonType.NO)
when (userSelection) { when (userSelection) {
ButtonType.YES -> presenter.fetchAccountTransactionsAsync(response.account) { } ButtonType.YES -> presenter.fetchAccountTransactionsAsync(response.customer) { }
else -> { } // nothing to do then, simply close dialog else -> { } // nothing to do then, simply close dialog
} }

View File

@ -114,7 +114,7 @@ open class TransferMoneyDialog @JvmOverloads constructor(
cellFormat { cellFormat {
text = it.displayNameIncludingBankName text = it.displayNameIncludingBankName
it.account.bank.iconUrl?.let { iconUrl -> it.customer.bank.iconUrl?.let { iconUrl ->
graphic = ImageView(iconUrl)?.apply { graphic = ImageView(iconUrl)?.apply {
this.fitHeight = BankIconSize this.fitHeight = BankIconSize
this.fitWidth = BankIconSize this.fitWidth = BankIconSize

View File

@ -10,7 +10,7 @@ import javafx.scene.text.FontWeight
import net.dankito.banking.ui.javafx.dialogs.tan.controls.ChipTanFlickerCodeView import net.dankito.banking.ui.javafx.dialogs.tan.controls.ChipTanFlickerCodeView
import net.dankito.banking.ui.javafx.dialogs.JavaFxDialogService import net.dankito.banking.ui.javafx.dialogs.JavaFxDialogService
import net.dankito.banking.ui.javafx.dialogs.tan.controls.TanImageView import net.dankito.banking.ui.javafx.dialogs.tan.controls.TanImageView
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.responses.BankingClientResponse import net.dankito.banking.ui.model.responses.BankingClientResponse
import net.dankito.banking.ui.model.tan.* import net.dankito.banking.ui.model.tan.*
import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.banking.ui.presenter.BankingPresenter
@ -20,7 +20,7 @@ import tornadofx.*
open class EnterTanDialog( open class EnterTanDialog(
protected val account: Account, protected val customer: Customer,
protected val challenge: TanChallenge, protected val challenge: TanChallenge,
protected val presenter: BankingPresenter, protected val presenter: BankingPresenter,
protected val tanEnteredCallback: (EnterTanResult) -> Unit protected val tanEnteredCallback: (EnterTanResult) -> Unit
@ -41,11 +41,11 @@ open class EnterTanDialog(
protected var tanImageView: TanImageView? = null protected var tanImageView: TanImageView? = null
protected val tanProceduresWithoutUnsupported = account.supportedTanProcedures.filterNot { it.type == TanProcedureType.ChipTanUsb } // USB tan generators are not supported protected val tanProceduresWithoutUnsupported = customer.supportedTanProcedures.filterNot { it.type == TanProcedureType.ChipTanUsb } // USB tan generators are not supported
protected val selectedTanProcedure = SimpleObjectProperty<TanProcedure>(account.selectedTanProcedure ?: tanProceduresWithoutUnsupported.firstOrNull { it.displayName.contains("manuell", true) == false } ?: tanProceduresWithoutUnsupported.firstOrNull()) protected val selectedTanProcedure = SimpleObjectProperty<TanProcedure>(customer.selectedTanProcedure ?: tanProceduresWithoutUnsupported.firstOrNull { it.displayName.contains("manuell", true) == false } ?: tanProceduresWithoutUnsupported.firstOrNull())
protected val selectedTanMedium = SimpleObjectProperty<TanMedium>(account.tanMediaSorted.firstOrNull()) protected val selectedTanMedium = SimpleObjectProperty<TanMedium>(customer.tanMediaSorted.firstOrNull())
protected val enteredTan = SimpleStringProperty("") protected val enteredTan = SimpleStringProperty("")
@ -84,13 +84,13 @@ open class EnterTanDialog(
} }
} }
if (account.tanMediaSorted.isNotEmpty()) { if (customer.tanMediaSorted.isNotEmpty()) {
field(messages["enter.tan.dialog.select.tan.medium"]) { field(messages["enter.tan.dialog.select.tan.medium"]) {
label.apply { label.apply {
font = Font.font(font.family, FontWeight.BLACK, font.size) font = Font.font(font.family, FontWeight.BLACK, font.size)
} }
combobox(selectedTanMedium, account.tanMediaSorted) { combobox(selectedTanMedium, customer.tanMediaSorted) {
cellFormat { cellFormat {
text = it.displayName text = it.displayName
} }

View File

@ -2,10 +2,10 @@ package net.dankito.banking.ui.javafx.model
import javafx.scene.Node import javafx.scene.Node
import javafx.scene.image.ImageView import javafx.scene.image.ImageView
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
open class AccountsAccountTreeItem(val account: Account) : AccountsTreeItemBase(account.displayName) { open class AccountsAccountTreeItem(val customer: Customer) : AccountsTreeItemBase(customer.displayName) {
companion object { companion object {
private const val IconSize = 16.0 private const val IconSize = 16.0
@ -17,13 +17,13 @@ open class AccountsAccountTreeItem(val account: Account) : AccountsTreeItemBase(
graphic = createIconImageView() graphic = createIconImageView()
account.bankAccounts.forEach { bankAccount -> customer.bankAccounts.forEach { bankAccount ->
children.add(AccountsBankAccountTreeItem(bankAccount)) children.add(AccountsBankAccountTreeItem(bankAccount))
} }
} }
protected open fun createIconImageView(): Node? { protected open fun createIconImageView(): Node? {
account.bank.iconUrl?.let { customer.bank.iconUrl?.let {
val iconImageView = ImageView(it) val iconImageView = ImageView(it)
iconImageView.fitHeight = IconSize iconImageView.fitHeight = IconSize

View File

@ -2,26 +2,26 @@ package net.dankito.banking.ui.javafx.model
import javafx.collections.ListChangeListener import javafx.collections.ListChangeListener
import javafx.collections.ObservableList import javafx.collections.ObservableList
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import tornadofx.FX.Companion.messages import tornadofx.FX.Companion.messages
import tornadofx.get import tornadofx.get
import tornadofx.runLater import tornadofx.runLater
open class AccountsRootTreeItem(accounts: ObservableList<Account>) : AccountsTreeItemBase(messages["accounts.view.all.accounts"]) { open class AccountsRootTreeItem(customers: ObservableList<Customer>) : AccountsTreeItemBase(messages["accounts.view.all.accounts"]) {
init { init {
setAccounts(accounts) setAccounts(customers)
accounts.addListener(ListChangeListener { customers.addListener(ListChangeListener {
runLater { setAccounts(accounts) } runLater { setAccounts(customers) }
}) })
} }
protected open fun setAccounts(accounts: List<Account>) { protected open fun setAccounts(customers: List<Customer>) {
isExpanded = accounts.isNotEmpty() isExpanded = customers.isNotEmpty()
children.setAll(accounts.map { AccountsAccountTreeItem(it) }) children.setAll(customers.map { AccountsAccountTreeItem(it) })
} }
} }

View File

@ -1,17 +1,17 @@
package net.dankito.banking.persistence package net.dankito.banking.persistence
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
interface IBankingPersistence { interface IBankingPersistence {
fun saveOrUpdateAccount(account: Account, allAccounts: List<Account>) fun saveOrUpdateAccount(customer: Customer, allCustomers: List<Customer>)
fun deleteAccount(account: Account, allAccounts: List<Account>) fun deleteAccount(customer: Customer, allCustomers: List<Customer>)
fun readPersistedAccounts(): List<Account> fun readPersistedAccounts(): List<Customer>
fun saveOrUpdateAccountTransactions(bankAccount: BankAccount, transactions: List<AccountTransaction>) fun saveOrUpdateAccountTransactions(bankAccount: BankAccount, transactions: List<AccountTransaction>)

View File

@ -1,6 +1,6 @@
package net.dankito.banking.ui package net.dankito.banking.ui
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult
import net.dankito.banking.ui.model.tan.EnterTanResult import net.dankito.banking.ui.model.tan.EnterTanResult
import net.dankito.banking.ui.model.tan.TanChallenge import net.dankito.banking.ui.model.tan.TanChallenge
@ -9,7 +9,7 @@ import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium
interface BankingClientCallback { interface BankingClientCallback {
fun enterTan(account: Account, tanChallenge: TanChallenge): EnterTanResult fun enterTan(customer: Customer, tanChallenge: TanChallenge): EnterTanResult
/** /**
* This method gets called for chipTan TAN generators when the bank asks the customer to synchronize her/his TAN generator. * This method gets called for chipTan TAN generators when the bank asks the customer to synchronize her/his TAN generator.

View File

@ -1,6 +1,6 @@
package net.dankito.banking.ui package net.dankito.banking.ui
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.parameters.TransferMoneyData import net.dankito.banking.ui.model.parameters.TransferMoneyData
import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult
@ -14,7 +14,7 @@ interface IRouter {
fun showAddAccountDialog(presenter: BankingPresenter) fun showAddAccountDialog(presenter: BankingPresenter)
fun getTanFromUserFromNonUiThread(account: Account, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult fun getTanFromUserFromNonUiThread(customer: Customer, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult
fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult

View File

@ -8,7 +8,7 @@ import java.util.*
@JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references @JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references
open class BankAccount @JvmOverloads constructor( open class BankAccount @JvmOverloads constructor(
val account: Account, val customer: Customer,
val identifier: String, val identifier: String,
var accountHolderName: String, var accountHolderName: String,
var iban: String?, var iban: String?,
@ -27,7 +27,7 @@ open class BankAccount @JvmOverloads constructor(
bookedAccountTransactions: List<AccountTransaction> = listOf() bookedAccountTransactions: List<AccountTransaction> = listOf()
) { ) {
internal constructor() : this(Account(), "", "", null, null, "") // for object deserializers internal constructor() : this(Customer(), "", "", null, null, "") // for object deserializers
var id: String = UUID.randomUUID().toString() var id: String = UUID.randomUUID().toString()
@ -47,7 +47,7 @@ open class BankAccount @JvmOverloads constructor(
} }
val displayNameIncludingBankName: String val displayNameIncludingBankName: String
get() = "${account.bank.name} ${displayName}" get() = "${customer.bank.name} ${displayName}"
var bookedTransactions: List<AccountTransaction> = bookedAccountTransactions var bookedTransactions: List<AccountTransaction> = bookedAccountTransactions

View File

@ -10,7 +10,7 @@ import java.util.*
@JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references @JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references
open class Account( open class Customer(
val bank: Bank, val bank: Bank,
val customerId: String, val customerId: String,
var password: String, var password: String,

View File

@ -6,7 +6,7 @@ import java.util.*
open class MessageLogEntry( open class MessageLogEntry(
val message: String, val message: String,
val time: Date, val time: Date,
val account: Account val customer: Customer
) { ) {
override fun toString(): String { override fun toString(): String {

View File

@ -1,6 +1,6 @@
package net.dankito.banking.ui.model.responses package net.dankito.banking.ui.model.responses
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import java.math.BigDecimal import java.math.BigDecimal
@ -9,7 +9,7 @@ import java.math.BigDecimal
open class AddAccountResponse( open class AddAccountResponse(
isSuccessful: Boolean, isSuccessful: Boolean,
errorToShowToUser: String?, errorToShowToUser: String?,
val account: Account, val customer: Customer,
val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false, val supportsRetrievingTransactionsOfLast90DaysWithoutTan: Boolean = false,
val bookedTransactionsOfLast90Days: Map<BankAccount, List<AccountTransaction>> = mapOf(), val bookedTransactionsOfLast90Days: Map<BankAccount, List<AccountTransaction>> = mapOf(),
val unbookedTransactionsOfLast90Days: Map<BankAccount, List<Any>> = mapOf(), val unbookedTransactionsOfLast90Days: Map<BankAccount, List<Any>> = mapOf(),
@ -20,7 +20,7 @@ open class AddAccountResponse(
: BankingClientResponse(isSuccessful, errorToShowToUser, error, userCancelledAction) { : BankingClientResponse(isSuccessful, errorToShowToUser, error, userCancelledAction) {
override fun toString(): String { override fun toString(): String {
return account.toString() + " " + super.toString() return customer.toString() + " " + super.toString()
} }
} }

View File

@ -66,7 +66,7 @@ open class BankingPresenter(
} }
protected val clientsForAccounts = mutableMapOf<Account, IBankingClient>() protected val bankingClientsForAccounts = mutableMapOf<Customer, IBankingClient>()
protected var selectedBankAccountsField = mutableListOf<BankAccount>() protected var selectedBankAccountsField = mutableListOf<BankAccount>()
@ -75,7 +75,7 @@ open class BankingPresenter(
protected var saveAccountOnNextEnterTanInvocation = false protected var saveAccountOnNextEnterTanInvocation = false
protected val accountsChangedListeners = mutableListOf<(List<Account>) -> Unit>() protected val accountsChangedListeners = mutableListOf<(List<Customer>) -> Unit>()
protected val retrievedAccountTransactionsResponseListeners = mutableListOf<(GetTransactionsResponse) -> Unit>() protected val retrievedAccountTransactionsResponseListeners = mutableListOf<(GetTransactionsResponse) -> Unit>()
@ -84,13 +84,13 @@ open class BankingPresenter(
protected val callback: BankingClientCallback = object : BankingClientCallback { protected val callback: BankingClientCallback = object : BankingClientCallback {
override fun enterTan(account: Account, tanChallenge: TanChallenge): EnterTanResult { override fun enterTan(customer: Customer, tanChallenge: TanChallenge): EnterTanResult {
if (saveAccountOnNextEnterTanInvocation) { if (saveAccountOnNextEnterTanInvocation) {
persistAccount(account) persistAccount(customer)
saveAccountOnNextEnterTanInvocation = false saveAccountOnNextEnterTanInvocation = false
} }
val result = router.getTanFromUserFromNonUiThread(account, tanChallenge, this@BankingPresenter) val result = router.getTanFromUserFromNonUiThread(customer, tanChallenge, this@BankingPresenter)
if (result.changeTanProcedureTo != null || result.changeTanMediumTo != null) { // then either selected TAN medium or procedure will change -> save account on next call to enterTan() as then changes will be visible if (result.changeTanProcedureTo != null || result.changeTanMediumTo != null) { // then either selected TAN medium or procedure will change -> save account on next call to enterTan() as then changes will be visible
saveAccountOnNextEnterTanInvocation = true saveAccountOnNextEnterTanInvocation = true
@ -125,21 +125,21 @@ open class BankingPresenter(
try { try {
val deserializedAccounts = persister.readPersistedAccounts() val deserializedAccounts = persister.readPersistedAccounts()
deserializedAccounts.forEach { account -> deserializedAccounts.forEach { customer ->
val bank = account.bank val bank = customer.bank
val bankInfo = BankInfo(bank.name, bank.bankCode, bank.bic, "", "", "", bank.finTsServerAddress, "FinTS V3.0", null) val bankInfo = BankInfo(bank.name, bank.bankCode, bank.bic, "", "", "", bank.finTsServerAddress, "FinTS V3.0", null)
val newClient = bankingClientCreator.createClient(bankInfo, account.customerId, account.password, val newClient = bankingClientCreator.createClient(bankInfo, customer.customerId, customer.password,
dataFolder, threadPool, callback) dataFolder, threadPool, callback)
try { try {
newClient.restoreData() newClient.restoreData()
} catch (e: Exception) { } catch (e: Exception) {
log.error("Could not deserialize account data of $account", e) log.error("Could not deserialize customer data of $customer", e)
// TODO: show error message to user // TODO: show error message to user
} }
addClientForAccount(account, newClient) addClientForAccount(customer, newClient)
} }
callAccountsChangedListeners() callAccountsChangedListeners()
@ -150,8 +150,8 @@ open class BankingPresenter(
} }
} }
protected open fun addClientForAccount(account: Account, client: IBankingClient) { protected open fun addClientForAccount(customer: Customer, client: IBankingClient) {
clientsForAccounts.put(account, client) bankingClientsForAccounts.put(customer, client)
} }
@ -163,7 +163,7 @@ open class BankingPresenter(
val startDate = Date() val startDate = Date()
newClient.addAccountAsync { response -> newClient.addAccountAsync { response ->
val account = response.account val account = response.customer
if (response.isSuccessful) { if (response.isSuccessful) {
addClientForAccount(account, newClient) addClientForAccount(account, newClient)
@ -191,14 +191,14 @@ open class BankingPresenter(
} }
} }
protected open fun findIconForBankAsync(account: Account) { protected open fun findIconForBankAsync(customer: Customer) {
threadPool.runAsync { threadPool.runAsync {
findIconForBank(account) findIconForBank(customer)
} }
} }
protected open fun findIconForBank(account: Account) { protected open fun findIconForBank(customer: Customer) {
val bank = account.bank val bank = customer.bank
try { try {
bankIconFinder.findIconForBank(bank.name)?.let { bankIconUrl -> bankIconFinder.findIconForBank(bank.name)?.let { bankIconUrl ->
@ -206,7 +206,7 @@ open class BankingPresenter(
bank.iconUrl = "file://" + bankIconFile.absolutePath // without 'file://' Android will not find it bank.iconUrl = "file://" + bankIconFile.absolutePath // without 'file://' Android will not find it
persistAccount(account) persistAccount(customer)
callAccountsChangedListeners() callAccountsChangedListeners()
} }
@ -250,13 +250,13 @@ open class BankingPresenter(
} }
open fun deleteAccount(account: Account) { open fun deleteAccount(customer: Customer) {
val wasSelected = isSingleSelectedAccount(account) or // either account or one of its bank accounts is currently selected val wasSelected = isSingleSelectedAccount(customer) or // either account or one of its bank accounts is currently selected
(account.bankAccounts.firstOrNull { isSingleSelectedBankAccount(it) } != null) (customer.bankAccounts.firstOrNull { isSingleSelectedBankAccount(it) } != null)
clientsForAccounts.remove(account) bankingClientsForAccounts.remove(customer)
persister.deleteAccount(account, accounts) persister.deleteAccount(customer, customers)
callAccountsChangedListeners() callAccountsChangedListeners()
@ -266,10 +266,10 @@ open class BankingPresenter(
} }
open fun fetchAccountTransactionsAsync(account: Account, open fun fetchAccountTransactionsAsync(customer: Customer,
callback: (GetTransactionsResponse) -> Unit) { callback: (GetTransactionsResponse) -> Unit) {
account.bankAccounts.forEach { bankAccount -> customer.bankAccounts.forEach { bankAccount ->
if (bankAccount.supportsRetrievingAccountTransactions) { if (bankAccount.supportsRetrievingAccountTransactions) {
fetchAccountTransactionsAsync(bankAccount, callback) // TODO: use a synchronous version of fetchAccountTransactions() so that all bank accounts get handled serially fetchAccountTransactionsAsync(bankAccount, callback) // TODO: use a synchronous version of fetchAccountTransactions() so that all bank accounts get handled serially
} }
@ -285,7 +285,7 @@ open class BankingPresenter(
open fun fetchAccountTransactionsAsync(bankAccount: BankAccount, fromDate: Date?, abortIfTanIsRequired: Boolean = false, open fun fetchAccountTransactionsAsync(bankAccount: BankAccount, fromDate: Date?, abortIfTanIsRequired: Boolean = false,
callback: (GetTransactionsResponse) -> Unit) { callback: (GetTransactionsResponse) -> Unit) {
getClientForAccount(bankAccount.account)?.let { client -> getBankingClientForAccount(bankAccount.customer)?.let { client ->
val startDate = Date() val startDate = Date()
client.getTransactionsAsync(bankAccount, GetTransactionsParameter(true, fromDate, null, abortIfTanIsRequired, { receivedAccountsTransactionChunk(bankAccount, it) } )) { response -> client.getTransactionsAsync(bankAccount, GetTransactionsParameter(true, fromDate, null, abortIfTanIsRequired, { receivedAccountsTransactionChunk(bankAccount, it) } )) { response ->
@ -308,7 +308,7 @@ open class BankingPresenter(
} }
protected open fun updateAccountsTransactionsAsync(abortIfTanIsRequired: Boolean = false, callback: (GetTransactionsResponse) -> Unit) { protected open fun updateAccountsTransactionsAsync(abortIfTanIsRequired: Boolean = false, callback: (GetTransactionsResponse) -> Unit) {
clientsForAccounts.keys.forEach { account -> bankingClientsForAccounts.keys.forEach { account ->
account.bankAccounts.forEach { bankAccount -> account.bankAccounts.forEach { bankAccount ->
if (bankAccount.supportsRetrievingAccountTransactions) { if (bankAccount.supportsRetrievingAccountTransactions) {
updateBankAccountTransactionsAsync(bankAccount, abortIfTanIsRequired, callback) updateBankAccountTransactionsAsync(bankAccount, abortIfTanIsRequired, callback)
@ -353,7 +353,7 @@ open class BankingPresenter(
bankAccount.balance = it bankAccount.balance = it
} }
persistAccount(bankAccount.account) // only needed because of balance persistAccount(bankAccount.customer) // only needed because of balance
persistAccountTransactions(bankAccount, response.bookedTransactions, response.unbookedTransactions) persistAccountTransactions(bankAccount, response.bookedTransactions, response.unbookedTransactions)
} }
@ -362,8 +362,8 @@ open class BankingPresenter(
} }
protected open fun persistAccount(account: Account) { protected open fun persistAccount(customer: Customer) {
persister.saveOrUpdateAccount(account, accounts) persister.saveOrUpdateAccount(customer, customers)
} }
protected open fun persistAccountTransactions(bankAccount: BankAccount, bookedTransactions: List<AccountTransaction>, unbookedTransactions: List<Any>) { protected open fun persistAccountTransactions(bankAccount: BankAccount, bookedTransactions: List<AccountTransaction>, unbookedTransactions: List<Any>) {
@ -374,7 +374,7 @@ open class BankingPresenter(
open fun transferMoneyAsync(bankAccount: BankAccount, data: TransferMoneyData, callback: (BankingClientResponse) -> Unit) { open fun transferMoneyAsync(bankAccount: BankAccount, data: TransferMoneyData, callback: (BankingClientResponse) -> Unit) {
getClientForAccount(bankAccount.account)?.let { client -> getBankingClientForAccount(bankAccount.customer)?.let { client ->
client.transferMoneyAsync(data, bankAccount) { response -> client.transferMoneyAsync(data, bankAccount) { response ->
if (response.isSuccessful) { if (response.isSuccessful) {
updateBankAccountTransactionsAsync(bankAccount, true) { } updateBankAccountTransactionsAsync(bankAccount, true) { }
@ -485,13 +485,13 @@ open class BankingPresenter(
} }
open fun getMessageLogForAccounts(accounts: List<Account>): List<String> { open fun getMessageLogForAccounts(customers: List<Customer>): List<String> {
val logEntries = accounts.flatMap { val logEntries = customers.flatMap {
getClientForAccount(it)?.messageLogWithoutSensitiveData ?: listOf() getBankingClientForAccount(it)?.messageLogWithoutSensitiveData ?: listOf()
} }
return logEntries.map { entry -> return logEntries.map { entry ->
MessageLogEntryDateFormat.format(entry.time) + " " + entry.account.bank.bankCode + " " + entry.message MessageLogEntryDateFormat.format(entry.time) + " " + entry.customer.bank.bankCode + " " + entry.message
} }
} }
@ -509,8 +509,8 @@ open class BankingPresenter(
} }
protected open fun getClientForAccount(account: Account): IBankingClient? { protected open fun getBankingClientForAccount(customer: Customer): IBankingClient? {
return clientsForAccounts.get(account) return bankingClientsForAccounts.get(customer)
} }
@ -527,9 +527,9 @@ open class BankingPresenter(
open val areAllAccountSelected: Boolean open val areAllAccountSelected: Boolean
get() = selectedAccountType == SelectedAccountType.AllAccounts get() = selectedAccountType == SelectedAccountType.AllAccounts
open fun isSingleSelectedAccount(account: Account): Boolean { open fun isSingleSelectedAccount(customer: Customer): Boolean {
return selectedAccountType == SelectedAccountType.SingleAccount return selectedAccountType == SelectedAccountType.SingleAccount
&& selectedBankAccountsField.map { it.account }.toSet().containsExactly(account) && selectedBankAccountsField.map { it.customer }.toSet().containsExactly(customer)
} }
open fun isSingleSelectedBankAccount(bankAccount: BankAccount): Boolean { open fun isSingleSelectedBankAccount(bankAccount: BankAccount): Boolean {
@ -543,10 +543,10 @@ open class BankingPresenter(
setSelectedBankAccounts(bankAccounts) setSelectedBankAccounts(bankAccounts)
} }
open fun selectedAccount(account: Account) { open fun selectedAccount(customer: Customer) {
selectedAccountType = SelectedAccountType.SingleAccount selectedAccountType = SelectedAccountType.SingleAccount
setSelectedBankAccounts(account.bankAccounts) setSelectedBankAccounts(customer.bankAccounts)
} }
open fun selectedBankAccount(bankAccount: BankAccount) { open fun selectedBankAccount(bankAccount: BankAccount) {
@ -562,17 +562,17 @@ open class BankingPresenter(
} }
open val accounts: List<Account> open val customers: List<Customer>
get() = clientsForAccounts.keys.toList() get() = bankingClientsForAccounts.keys.toList()
open val bankAccounts: List<BankAccount> open val bankAccounts: List<BankAccount>
get() = accounts.flatMap { it.bankAccounts } get() = customers.flatMap { it.bankAccounts }
open val allTransactions: List<AccountTransaction> open val allTransactions: List<AccountTransaction>
get() = getAccountTransactionsForBankAccounts(bankAccounts) get() = getAccountTransactionsForBankAccounts(bankAccounts)
open val balanceOfAllAccounts: BigDecimal open val balanceOfAllAccounts: BigDecimal
get() = getBalanceForAccounts(accounts) get() = getBalanceForAccounts(customers)
open val bankAccountsSupportingRetrievingAccountTransactions: List<BankAccount> open val bankAccountsSupportingRetrievingAccountTransactions: List<BankAccount>
@ -621,8 +621,8 @@ open class BankingPresenter(
return bankAccounts.flatMap { it.bookedTransactions }.sortedByDescending { it.valueDate } // TODO: someday add unbooked transactions return bankAccounts.flatMap { it.bookedTransactions }.sortedByDescending { it.valueDate } // TODO: someday add unbooked transactions
} }
protected open fun getBalanceForAccounts(accounts: Collection<Account>): BigDecimal { protected open fun getBalanceForAccounts(customers: Collection<Customer>): BigDecimal {
return accounts.map { it.balance }.fold(BigDecimal.ZERO) { acc, e -> acc + e } return customers.map { it.balance }.fold(BigDecimal.ZERO) { acc, e -> acc + e }
} }
protected open fun sumBalance(singleBalances: Collection<BigDecimal>): BigDecimal { protected open fun sumBalance(singleBalances: Collection<BigDecimal>): BigDecimal {
@ -660,16 +660,16 @@ open class BankingPresenter(
} }
open fun addAccountsChangedListener(listener: (List<Account>) -> Unit): Boolean { open fun addAccountsChangedListener(listener: (List<Customer>) -> Unit): Boolean {
return accountsChangedListeners.add(listener) return accountsChangedListeners.add(listener)
} }
open fun removeAccountsChangedListener(listener: (List<Account>) -> Unit): Boolean { open fun removeAccountsChangedListener(listener: (List<Customer>) -> Unit): Boolean {
return accountsChangedListeners.add(listener) return accountsChangedListeners.add(listener)
} }
protected open fun callAccountsChangedListeners() { protected open fun callAccountsChangedListeners() {
val accounts = this.accounts val accounts = this.customers
ArrayList(accountsChangedListeners).forEach { ArrayList(accountsChangedListeners).forEach {
it(accounts) // TODO: use RxJava for this it(accounts) // TODO: use RxJava for this

View File

@ -6,7 +6,7 @@ import com.soywiz.klock.jvm.toDate
import net.dankito.banking.extensions.toKlockDate import net.dankito.banking.extensions.toKlockDate
import net.dankito.banking.ui.BankingClientCallback import net.dankito.banking.ui.BankingClientCallback
import net.dankito.banking.ui.IBankingClient import net.dankito.banking.ui.IBankingClient
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.MessageLogEntry import net.dankito.banking.ui.model.MessageLogEntry
import net.dankito.banking.ui.model.parameters.GetTransactionsParameter import net.dankito.banking.ui.model.parameters.GetTransactionsParameter
@ -61,12 +61,12 @@ open class fints4kBankingClient(
protected val bank = bankDataMapper.mapFromBankInfo(bankInfo) protected val bank = bankDataMapper.mapFromBankInfo(bankInfo)
protected val customer = CustomerData(customerId, pin) protected val fints4kCustomer = CustomerData(customerId, pin)
protected var account: Account = mapper.mapAccount(customer, bank) // temporary save temp account, we update with data from server response like BankAccounts later protected var customer: Customer = mapper.mapCustomer(fints4kCustomer, bank) // temporary save temp customer, we update with data from server response like BankAccounts later
protected val client = FinTsClientForCustomer(bank, customer, object : FinTsClientCallback { protected val client = FinTsClientForCustomer(bank, fints4kCustomer, object : FinTsClientCallback {
override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?): TanProcedure? { override fun askUserForTanProcedure(supportedTanProcedures: List<TanProcedure>, suggestedTanProcedure: TanProcedure?): TanProcedure? {
// we simply return suggestedTanProcedure as even so it's not user's preferred TAN procedure she still can select it in EnterTanDialog // we simply return suggestedTanProcedure as even so it's not user's preferred TAN procedure she still can select it in EnterTanDialog
@ -74,15 +74,15 @@ open class fints4kBankingClient(
} }
override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge): EnterTanResult { override fun enterTan(customer: CustomerData, tanChallenge: TanChallenge): EnterTanResult {
mapper.updateTanMediaAndProcedures(account, customer) mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, customer)
val result = callback.enterTan(account, mapper.mapTanChallenge(tanChallenge)) val result = callback.enterTan(this@fints4kBankingClient.customer, mapper.mapTanChallenge(tanChallenge))
return mapper.mapEnterTanResult(result, customer) return mapper.mapEnterTanResult(result, customer)
} }
override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult { override fun enterTanGeneratorAtc(customer: CustomerData, tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
mapper.updateTanMediaAndProcedures(account, customer) mapper.updateTanMediaAndProcedures(this@fints4kBankingClient.customer, customer)
val result = callback.enterTanGeneratorAtc(mapper.mapTanMedium(tanMedium)) val result = callback.enterTanGeneratorAtc(mapper.mapTanMedium(tanMedium))
@ -93,13 +93,13 @@ open class fints4kBankingClient(
override val messageLogWithoutSensitiveData: List<MessageLogEntry> override val messageLogWithoutSensitiveData: List<MessageLogEntry>
get() = client.messageLogWithoutSensitiveData.map { MessageLogEntry(it.message, it.time.toDate(), account) } get() = client.messageLogWithoutSensitiveData.map { MessageLogEntry(it.message, it.time.toDate(), customer) }
override fun addAccountAsync(callback: (AddAccountResponse) -> Unit) { override fun addAccountAsync(callback: (AddAccountResponse) -> Unit) {
client.addAccountAsync { response -> client.addAccountAsync { response ->
this.account = mapper.mapAccount(customer, bank) this.customer = mapper.mapCustomer(fints4kCustomer, bank)
val mappedResponse = mapper.mapResponse(account, response) val mappedResponse = mapper.mapResponse(customer, response)
saveData() saveData()
@ -108,7 +108,7 @@ open class fints4kBankingClient(
} }
override fun getTransactionsAsync(bankAccount: BankAccount, parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) { override fun getTransactionsAsync(bankAccount: BankAccount, parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
val account = mapper.findAccountForBankAccount(customer, bankAccount) val account = mapper.findAccountForBankAccount(fints4kCustomer, bankAccount)
if (account == null) { // TODO: in this case retrieve data from bank, all data should be re-creatable if (account == null) { // TODO: in this case retrieve data from bank, all data should be re-creatable
callback(GetTransactionsResponse(bankAccount, false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate callback(GetTransactionsResponse(bankAccount, false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate
@ -127,7 +127,7 @@ open class fints4kBankingClient(
} }
override fun transferMoneyAsync(data: TransferMoneyData, bankAccount: BankAccount, callback: (BankingClientResponse) -> Unit) { override fun transferMoneyAsync(data: TransferMoneyData, bankAccount: BankAccount, callback: (BankingClientResponse) -> Unit) {
val account = mapper.findAccountForBankAccount(customer, bankAccount) val account = mapper.findAccountForBankAccount(fints4kCustomer, bankAccount)
if (account == null) { if (account == null) {
callback(BankingClientResponse(false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate callback(BankingClientResponse(false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate
@ -148,9 +148,9 @@ open class fints4kBankingClient(
val deserializedCustomer = serializer.deserializeObject(getFints4kClientDataFile(), CustomerData::class.java) val deserializedCustomer = serializer.deserializeObject(getFints4kClientDataFile(), CustomerData::class.java)
deserializedCustomer?.let { deserializedCustomer?.let {
mapper.updateCustomer(customer, deserializedCustomer) mapper.updateCustomer(fints4kCustomer, deserializedCustomer)
account = mapper.mapAccount(customer, bank) customer = mapper.mapCustomer(fints4kCustomer, bank)
} }
} }
@ -160,14 +160,14 @@ open class fints4kBankingClient(
clientDataFile.parentFile.mkdirs() clientDataFile.parentFile.mkdirs()
serializer.serializeObject(customer, clientDataFile) serializer.serializeObject(fints4kCustomer, clientDataFile)
} catch (e: Exception) { } catch (e: Exception) {
log.error("Could not save customer data for $customer", e) log.error("Could not save customer data for $fints4kCustomer", e)
} }
} }
protected open fun getFints4kClientDataFile(): File { protected open fun getFints4kClientDataFile(): File {
return File(File(dataFolder, "fints4k-client"), "${bank.bankCode}_${customer.customerId}_$fints4kClientDataFilename") return File(File(dataFolder, "fints4k-client"), "${bank.bankCode}_${fints4kCustomer.customerId}_$fints4kClientDataFilename")
} }
} }

View File

@ -29,21 +29,21 @@ open class fints4kModelMapper {
return BankingClientResponse(response.isSuccessful, mapErrorToShowToUser(response), response.exception, response.userCancelledAction) return BankingClientResponse(response.isSuccessful, mapErrorToShowToUser(response), response.exception, response.userCancelledAction)
} }
open fun mapResponse(account: Account, response: net.dankito.banking.fints.response.client.AddAccountResponse): AddAccountResponse { open fun mapResponse(customer: Customer, response: net.dankito.banking.fints.response.client.AddAccountResponse): AddAccountResponse {
val balances = response.balances.mapKeys { findMatchingBankAccount(account, it.key) }.filter { it.key != null } val balances = response.balances.mapKeys { findMatchingBankAccount(customer, it.key) }.filter { it.key != null }
.mapValues { (it.value as Money).toJavaBigDecimal() } as Map<BankAccount, BigDecimal> .mapValues { (it.value as Money).toJavaBigDecimal() } as Map<BankAccount, BigDecimal>
val bookedTransactions = response.bookedTransactions.associateBy { it.account } val bookedTransactions = response.bookedTransactions.associateBy { it.account }
val mappedBookedTransactions = mutableMapOf<BankAccount, List<AccountTransaction>>() val mappedBookedTransactions = mutableMapOf<BankAccount, List<AccountTransaction>>()
bookedTransactions.keys.forEach { accountData -> bookedTransactions.keys.forEach { accountData ->
findMatchingBankAccount(account, accountData)?.let { bankAccount -> findMatchingBankAccount(customer, accountData)?.let { bankAccount ->
mappedBookedTransactions.put(bankAccount, mapTransactions(bankAccount, response.bookedTransactions)) mappedBookedTransactions.put(bankAccount, mapTransactions(bankAccount, response.bookedTransactions))
} }
} }
return AddAccountResponse(response.isSuccessful, mapErrorToShowToUser(response), return AddAccountResponse(response.isSuccessful, mapErrorToShowToUser(response),
account, response.supportsRetrievingTransactionsOfLast90DaysWithoutTan, customer, response.supportsRetrievingTransactionsOfLast90DaysWithoutTan,
mappedBookedTransactions, mappedBookedTransactions,
mapOf(), // TODO: map unbooked transactions mapOf(), // TODO: map unbooked transactions
balances, balances,
@ -71,16 +71,16 @@ open class fints4kModelMapper {
return Bank(bank.name, bank.bankCode, bank.bic, bank.finTs3ServerAddress) return Bank(bank.name, bank.bankCode, bank.bic, bank.finTs3ServerAddress)
} }
open fun mapAccount(customer: CustomerData, bank: BankData): Account { open fun mapCustomer(customer: CustomerData, bank: BankData): Customer {
val mappedBank = mapBank(bank) val mappedBank = mapBank(bank)
val account = Account(mappedBank, customer.customerId, customer.pin, customer.name, customer.userId) val mappedCustomer = Customer(mappedBank, customer.customerId, customer.pin, customer.name, customer.userId)
account.bankAccounts = mapBankAccounts(account, customer.accounts) mappedCustomer.bankAccounts = mapBankAccounts(mappedCustomer, customer.accounts)
updateTanMediaAndProcedures(account, customer) updateTanMediaAndProcedures(mappedCustomer, customer)
return account return mappedCustomer
} }
// TODO: move to a fints4k internal mapper // TODO: move to a fints4k internal mapper
@ -101,12 +101,12 @@ open class fints4kModelMapper {
} }
open fun mapBankAccounts(account: Account, accountData: List<AccountData>): List<BankAccount> { open fun mapBankAccounts(customer: Customer, accountData: List<AccountData>): List<BankAccount> {
return accountData.map { mapBankAccount(account, it) } return accountData.map { mapBankAccount(customer, it) }
} }
open fun mapBankAccount(account: Account, accountData: AccountData): BankAccount { open fun mapBankAccount(customer: Customer, accountData: AccountData): BankAccount {
return BankAccount(account, accountData.accountIdentifier, accountData.accountHolderName, accountData.iban, return BankAccount(customer, accountData.accountIdentifier, accountData.accountHolderName, accountData.iban,
accountData.subAccountAttribute, accountData.customerId, BigDecimal.ZERO, accountData.currency ?: "EUR", accountData.subAccountAttribute, accountData.customerId, BigDecimal.ZERO, accountData.currency ?: "EUR",
mapBankAccountType(accountData.accountType), accountData.productName, accountData.accountLimit, mapBankAccountType(accountData.accountType), accountData.productName, accountData.accountLimit,
null, accountData.supportsFeature(AccountFeature.RetrieveAccountTransactions), null, accountData.supportsFeature(AccountFeature.RetrieveAccountTransactions),
@ -165,8 +165,8 @@ open class fints4kModelMapper {
return customer.accounts.firstOrNull { bankAccount.identifier == it.accountIdentifier } return customer.accounts.firstOrNull { bankAccount.identifier == it.accountIdentifier }
} }
open fun findMatchingBankAccount(account: Account, accountData: AccountData): BankAccount? { open fun findMatchingBankAccount(customer: Customer, accountData: AccountData): BankAccount? {
return account.bankAccounts.firstOrNull { it.identifier == accountData.accountIdentifier } return customer.bankAccounts.firstOrNull { it.identifier == accountData.accountIdentifier }
} }
open fun findMatchingBankAccount(accounts: List<AccountData>, accountData: AccountData): AccountData? { open fun findMatchingBankAccount(accounts: List<AccountData>, accountData: AccountData): AccountData? {
@ -221,7 +221,7 @@ open class fints4kModelMapper {
} }
open fun updateTanMediaAndProcedures(account: Account, customer: CustomerData) { open fun updateTanMediaAndProcedures(account: Customer, customer: CustomerData) {
account.supportedTanProcedures = mapTanProcedures(customer.supportedTanProcedures) account.supportedTanProcedures = mapTanProcedures(customer.supportedTanProcedures)
if (customer.isTanProcedureSelected) { if (customer.isTanProcedureSelected) {
@ -262,8 +262,8 @@ open class fints4kModelMapper {
} }
} }
protected open fun findMappedTanProcedure(account: Account, tanProcedure: net.dankito.banking.fints.model.TanProcedure): TanProcedure? { protected open fun findMappedTanProcedure(customer: Customer, tanProcedure: net.dankito.banking.fints.model.TanProcedure): TanProcedure? {
return account.supportedTanProcedures.firstOrNull { it.bankInternalProcedureCode == tanProcedure.securityFunction.code } return customer.supportedTanProcedures.firstOrNull { it.bankInternalProcedureCode == tanProcedure.securityFunction.code }
} }

View File

@ -2,7 +2,7 @@ package net.dankito.banking
import net.dankito.banking.model.AccountCredentials import net.dankito.banking.model.AccountCredentials
import net.dankito.banking.ui.BankingClientCallback import net.dankito.banking.ui.BankingClientCallback
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.tan.FlickerCodeTanChallenge import net.dankito.banking.ui.model.tan.FlickerCodeTanChallenge
import net.dankito.banking.ui.model.tan.ImageTanChallenge import net.dankito.banking.ui.model.tan.ImageTanChallenge
import net.dankito.banking.ui.model.tan.TanChallenge import net.dankito.banking.ui.model.tan.TanChallenge
@ -24,7 +24,7 @@ import java.util.*
*/ */
open class HbciCallback( open class HbciCallback(
protected val credentials: AccountCredentials, protected val credentials: AccountCredentials,
protected val account: Account, protected val customer: Customer,
protected val mapper: hbci4jModelMapper, protected val mapper: hbci4jModelMapper,
protected val callback: BankingClientCallback protected val callback: BankingClientCallback
) : AbstractHBCICallback() { ) : AbstractHBCICallback() {
@ -85,13 +85,13 @@ open class HbciCallback(
// ADDED: Auswaehlen welches PinTan Verfahren verwendet werden soll // ADDED: Auswaehlen welches PinTan Verfahren verwendet werden soll
HBCICallback.NEED_PT_SECMECH -> selectTanProcedure(retData.toString())?.let { selectedTanProcedure -> HBCICallback.NEED_PT_SECMECH -> selectTanProcedure(retData.toString())?.let { selectedTanProcedure ->
account.selectedTanProcedure = selectedTanProcedure customer.selectedTanProcedure = selectedTanProcedure
retData.replace(0, retData.length, selectedTanProcedure.bankInternalProcedureCode) retData.replace(0, retData.length, selectedTanProcedure.bankInternalProcedureCode)
} }
// chipTan or simple TAN request (iTAN, smsTAN, ...) // chipTan or simple TAN request (iTAN, smsTAN, ...)
HBCICallback.NEED_PT_TAN -> { HBCICallback.NEED_PT_TAN -> {
getTanFromUser(account, msg, retData.toString())?.let { enteredTan -> getTanFromUser(customer, msg, retData.toString())?.let { enteredTan ->
retData.replace(0, retData.length, enteredTan) retData.replace(0, retData.length, enteredTan)
} }
} }
@ -100,7 +100,7 @@ open class HbciCallback(
HBCICallback.NEED_PT_QRTAN -> { // use class QRCode to display QR code HBCICallback.NEED_PT_QRTAN -> { // use class QRCode to display QR code
val qrData = retData.toString() val qrData = retData.toString()
val qrCode = QRCode(qrData, msg) val qrCode = QRCode(qrData, msg)
val enterTanResult = callback.enterTan(account, ImageTanChallenge(TanImage(qrCode.mimetype, qrCode.image), msg, account.selectedTanProcedure!!)) val enterTanResult = callback.enterTan(customer, ImageTanChallenge(TanImage(qrCode.mimetype, qrCode.image), msg, customer.selectedTanProcedure!!))
enterTanResult.enteredTan?.let { enteredTan -> enterTanResult.enteredTan?.let { enteredTan ->
retData.replace(0, retData.length, enteredTan) retData.replace(0, retData.length, enteredTan)
} }
@ -109,7 +109,7 @@ open class HbciCallback(
// photoTan // photoTan
HBCICallback.NEED_PT_PHOTOTAN -> { // use class MatrixCode to display photo HBCICallback.NEED_PT_PHOTOTAN -> { // use class MatrixCode to display photo
val matrixCode = MatrixCode(retData.toString()) val matrixCode = MatrixCode(retData.toString())
val enterTanResult = callback.enterTan(account, ImageTanChallenge(TanImage(matrixCode.mimetype, matrixCode.image), msg, account.selectedTanProcedure!!)) val enterTanResult = callback.enterTan(customer, ImageTanChallenge(TanImage(matrixCode.mimetype, matrixCode.image), msg, customer.selectedTanProcedure!!))
enterTanResult.enteredTan?.let { enteredTan -> enterTanResult.enteredTan?.let { enteredTan ->
retData.replace(0, retData.length, enteredTan) retData.replace(0, retData.length, enteredTan)
} }
@ -172,7 +172,7 @@ open class HbciCallback(
} }
open fun getTanFromUser(account: Account, messageToShowToUser: String, challengeHHD_UC: String): String? { open fun getTanFromUser(customer: Customer, messageToShowToUser: String, challengeHHD_UC: String): String? {
// Wenn per "retData" Daten uebergeben wurden, dann enthalten diese // Wenn per "retData" Daten uebergeben wurden, dann enthalten diese
// den fuer chipTAN optisch zu verwendenden Flickercode. // den fuer chipTAN optisch zu verwendenden Flickercode.
// Falls nicht, ist es eine TAN-Abfrage, fuer die keine weiteren // Falls nicht, ist es eine TAN-Abfrage, fuer die keine weiteren
@ -184,14 +184,14 @@ open class HbciCallback(
// werden. // werden.
val enterTanResult = if (challengeHHD_UC.isNullOrEmpty()) { val enterTanResult = if (challengeHHD_UC.isNullOrEmpty()) {
callback.enterTan(account, TanChallenge(messageToShowToUser, account.selectedTanProcedure!!)) callback.enterTan(customer, TanChallenge(messageToShowToUser, customer.selectedTanProcedure!!))
} }
else { else {
// for Sparkasse messageToShowToUser started with "chipTAN optisch\nTAN-Nummer\n\n" // for Sparkasse messageToShowToUser started with "chipTAN optisch\nTAN-Nummer\n\n"
val usefulMessage = messageToShowToUser.split("\n").last().trim() val usefulMessage = messageToShowToUser.split("\n").last().trim()
// val parsedDataSet = FlickerCode(challengeHHD_UC).render() // val parsedDataSet = FlickerCode(challengeHHD_UC).render()
callback.enterTan(account, FlickerCodeTanChallenge(net.dankito.banking.ui.model.tan.FlickerCode("", challengeHHD_UC), usefulMessage, account.selectedTanProcedure!!)) callback.enterTan(customer, FlickerCodeTanChallenge(net.dankito.banking.ui.model.tan.FlickerCode("", challengeHHD_UC), usefulMessage, customer.selectedTanProcedure!!))
} }
return enterTanResult.enteredTan return enterTanResult.enteredTan
@ -202,7 +202,7 @@ open class HbciCallback(
open fun selectTanProcedure(supportedTanProceduresString: String): net.dankito.banking.ui.model.tan.TanProcedure? { open fun selectTanProcedure(supportedTanProceduresString: String): net.dankito.banking.ui.model.tan.TanProcedure? {
val supportedTanProcedures = mapper.mapTanProcedures(supportedTanProceduresString) val supportedTanProcedures = mapper.mapTanProcedures(supportedTanProceduresString)
account.supportedTanProcedures = supportedTanProcedures customer.supportedTanProcedures = supportedTanProcedures
if (supportedTanProcedures.isNotEmpty()) { if (supportedTanProcedures.isNotEmpty()) {
// select any procedure, user then can select her preferred one in EnterTanDialog; try not to select 'chipTAN manuell' // select any procedure, user then can select her preferred one in EnterTanDialog; try not to select 'chipTAN manuell'

View File

@ -55,7 +55,7 @@ open class hbci4jBankingClient(
protected var bank = Bank(bankInfo.name, bankInfo.bankCode, bankInfo.bic, bankInfo.pinTanAddress ?: "") protected var bank = Bank(bankInfo.name, bankInfo.bankCode, bankInfo.bic, bankInfo.pinTanAddress ?: "")
protected var account = Account(bank, customerId, pin, "") protected var account = Customer(bank, customerId, pin, "")
protected val mapper = hbci4jModelMapper() protected val mapper = hbci4jModelMapper()
@ -93,13 +93,13 @@ open class hbci4jBankingClient(
return AddAccountResponse(false, null, account, error = connection.error) return AddAccountResponse(false, null, account, error = connection.error)
} }
protected open fun tryToRetrieveAccountTransactionsForAddedAccounts(account: Account): AddAccountResponse { protected open fun tryToRetrieveAccountTransactionsForAddedAccounts(customer: Customer): AddAccountResponse {
val transactionsOfLast90DaysResponses = mutableListOf<GetTransactionsResponse>() val transactionsOfLast90DaysResponses = mutableListOf<GetTransactionsResponse>()
val balances = mutableMapOf<BankAccount, BigDecimal>() val balances = mutableMapOf<BankAccount, BigDecimal>()
val bookedTransactions = mutableMapOf<BankAccount, List<AccountTransaction>>() val bookedTransactions = mutableMapOf<BankAccount, List<AccountTransaction>>()
val unbookedTransactions = mutableMapOf<BankAccount, List<Any>>() val unbookedTransactions = mutableMapOf<BankAccount, List<Any>>()
account.bankAccounts.forEach { bankAccount -> customer.bankAccounts.forEach { bankAccount ->
if (bankAccount.supportsRetrievingAccountTransactions) { if (bankAccount.supportsRetrievingAccountTransactions) {
val response = getTransactionsOfLast90Days(bankAccount) val response = getTransactionsOfLast90Days(bankAccount)
transactionsOfLast90DaysResponses.add(response) transactionsOfLast90DaysResponses.add(response)
@ -112,7 +112,7 @@ open class hbci4jBankingClient(
val supportsRetrievingTransactionsOfLast90DaysWithoutTan = transactionsOfLast90DaysResponses.firstOrNull { it.isSuccessful } != null val supportsRetrievingTransactionsOfLast90DaysWithoutTan = transactionsOfLast90DaysResponses.firstOrNull { it.isSuccessful } != null
return AddAccountResponse(true, null, account, supportsRetrievingTransactionsOfLast90DaysWithoutTan, return AddAccountResponse(true, null, customer, supportsRetrievingTransactionsOfLast90DaysWithoutTan,
bookedTransactions, unbookedTransactions, balances) bookedTransactions, unbookedTransactions, balances)
} }

View File

@ -1,6 +1,6 @@
package net.dankito.banking.util package net.dankito.banking.util
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Customer
import net.dankito.banking.ui.model.Bank import net.dankito.banking.ui.model.Bank
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.BankAccountType import net.dankito.banking.ui.model.BankAccountType
@ -39,11 +39,11 @@ open class hbci4jModelMapper {
} }
open fun mapBankAccounts(account: Account, bankAccounts: Array<out Konto>, passport: HBCIPassport): List<BankAccount> { open fun mapBankAccounts(customer: Customer, bankAccounts: Array<out Konto>, passport: HBCIPassport): List<BankAccount> {
return bankAccounts.map { bankAccount -> return bankAccounts.map { bankAccount ->
val iban = if (bankAccount.iban.isNullOrBlank() == false) bankAccount.iban else passport.upd.getProperty("KInfo.iban") ?: "" val iban = if (bankAccount.iban.isNullOrBlank() == false) bankAccount.iban else passport.upd.getProperty("KInfo.iban") ?: ""
BankAccount(account, bankAccount.number, BankAccount(customer, bankAccount.number,
if (bankAccount.name2.isNullOrBlank() == false) bankAccount.name + " " + bankAccount.name2 else bankAccount.name, if (bankAccount.name2.isNullOrBlank() == false) bankAccount.name + " " + bankAccount.name2 else bankAccount.name,
iban, bankAccount.subnumber, bankAccount.customerid, BigDecimal.ZERO, bankAccount.curr, mapBankAccountType(bankAccount), iban, bankAccount.subnumber, bankAccount.customerid, BigDecimal.ZERO, bankAccount.curr, mapBankAccountType(bankAccount),
null, bankAccount.limit?.value?.let { mapValue(it).toString() }, null, null, bankAccount.limit?.value?.let { mapValue(it).toString() }, null,