diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/parameter/TransferMoneyParameter.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/parameter/TransferMoneyParameter.kt index 71d6e2ed..ccb9f1ac 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/parameter/TransferMoneyParameter.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/client/model/parameter/TransferMoneyParameter.kt @@ -1,6 +1,7 @@ package net.dankito.banking.client.model.parameter import net.dankito.banking.client.model.BankAccountIdentifier +import net.dankito.banking.fints.model.AccountData import net.dankito.banking.fints.model.BankData import net.dankito.banking.fints.model.Money import net.dankito.banking.fints.model.TanMethodType @@ -35,6 +36,8 @@ open class TransferMoneyParameter( preferredTanMethods: List? = null, preferredTanMedium: String? = null, abortIfTanIsRequired: Boolean = false, - finTsModel: BankData? = null + finTsModel: BankData? = null, + + open val selectAccountToUseForTransfer: ((List) -> AccountData?)? = null // TODO: use BankAccount instead of AccountData ) : FinTsClientParameter(bankCode, loginName, password, preferredTanMethods, preferredTanMedium, abortIfTanIsRequired, finTsModel) \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt index b8c31123..6211f4ba 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt @@ -147,13 +147,23 @@ open class FinTsClient @JvmOverloads constructor( protected open suspend fun transferMoneyAsync(param: TransferMoneyParameter, recipientBankIdentifier: String, bank: BankData, accounts: List, previousJobResponse: FinTsClientResponse?): TransferMoneyResponse { val accountsSupportingTransfer = accounts.filter { it.supportsTransferringMoney } + val accountToUse: AccountData + if (accountsSupportingTransfer.isEmpty()) { return TransferMoneyResponse(ErrorCode.NoAccountSupportsMoneyTransfer, "None of the accounts $accounts supports money transfer", previousJobResponse?.messageLogWithoutSensitiveData ?: listOf(), bank) - } else if (accountsSupportingTransfer.size > 1) { - return TransferMoneyResponse(ErrorCode.MoreThanOneAccountSupportsMoneyTransfer, "More than one of the accounts $accountsSupportingTransfer supports money transfer, so we cannot clearly determine which one to use for this transfer", previousJobResponse?.messageLogWithoutSensitiveData ?: listOf(), bank) + } else if (accountsSupportingTransfer.size == 1) { + accountToUse = accountsSupportingTransfer.first() + } else { + val selectedAccount = param.selectAccountToUseForTransfer?.invoke(accountsSupportingTransfer) + + if (selectedAccount == null) { + return TransferMoneyResponse(ErrorCode.MoreThanOneAccountSupportsMoneyTransfer, "More than one of the accounts $accountsSupportingTransfer supports money transfer, so we cannot clearly determine which one to use for this transfer", previousJobResponse?.messageLogWithoutSensitiveData ?: listOf(), bank) + } + + accountToUse = selectedAccount } - val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, accountsSupportingTransfer.first()) + val context = JobContext(JobContextType.TransferMoney, this.callback, product, bank, accountToUse) val response = jobExecutor.transferMoneyAsync(context, BankTransferData(param.recipientName, param.recipientAccountIdentifier, recipientBankIdentifier, param.amount, param.reference, param.instantPayment)) diff --git a/fints4k/src/nativeMain/kotlin/commands/TransferMoneyCommand.kt b/fints4k/src/nativeMain/kotlin/commands/TransferMoneyCommand.kt index f9d42e27..33bb7e59 100644 --- a/fints4k/src/nativeMain/kotlin/commands/TransferMoneyCommand.kt +++ b/fints4k/src/nativeMain/kotlin/commands/TransferMoneyCommand.kt @@ -5,6 +5,7 @@ import com.github.ajalt.clikt.core.requireObject import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.options.option import net.dankito.banking.client.model.parameter.TransferMoneyParameter +import net.dankito.banking.fints.model.AccountData import net.dankito.banking.fints.model.Amount import net.dankito.banking.fints.model.Currency import net.dankito.banking.fints.model.Money @@ -16,7 +17,7 @@ class TransferMoneyCommand : CliktCommand("Transfers money from your account to val recipientAccountIdentifier by argument("Recipient account identifier", "In den meisten Fällen die IBAN des Empfängers") val amount by argument("Amount", "The amount to transfer to recipient") - val reference by argument("Reference", "Verwendungszweck. Max. 160 Zeichen, keine Sonderzeichen wie Umlaute etc.") + val reference by argument("Reference", "Verwendungszweck (optional). Max. 160 Zeichen, keine Sonderzeichen wie Umlaute etc.") val recipientBankIdentifier by option("-b", "--bic", help = "Recipient's Bank Identifier, in most cases the BIC. Muss nur für Auslands-Überweisungen angegeben werden. Für deutsche Banken kann die BIC aus der IBAN abgeleitet werden.") @@ -30,7 +31,31 @@ class TransferMoneyCommand : CliktCommand("Transfers money from your account to app.transferMoney(TransferMoneyParameter(bankCode, loginName, password, null, recipientName, recipientAccountIdentifier, recipientBankIdentifier, - Money(Amount(amount), Currency.DefaultCurrencyCode), reference, false, preferredTanMethods, abortIfTanIsRequired = abortIfRequiresTan)) + Money(Amount(amount), Currency.DefaultCurrencyCode), reference, false, preferredTanMethods, abortIfTanIsRequired = abortIfRequiresTan, + selectAccountToUseForTransfer = { accounts -> + selectAccountToUseForTransfer(accounts) + })) + } + + private fun selectAccountToUseForTransfer(accounts: List): AccountData? { + println("There are multiple accounts that support money transfer. Which one would you like to use?") + println() + + accounts.forEachIndexed { index, account -> + println("[${index + 1}] $account") + } + + println() + print("Enter the index of the account: ") + readLine()?.toIntOrNull()?.let { selectedIndex -> + if (selectedIndex > 0 && (selectedIndex - 1) < accounts.size) { + return accounts[selectedIndex - 1] + } + } + + println("Not a valid index entered. Valid indices are 1 - ${accounts.size}") // TODO: print this + "or enter an empty string to cancel" and loop for valid input? + + return null } } \ No newline at end of file