Implemented transferring money via command line

This commit is contained in:
dankito 2022-02-24 00:00:07 +01:00
parent ad826941dd
commit d442c02964
7 changed files with 100 additions and 10 deletions

View File

@ -16,6 +16,6 @@ open class FinTsClientResponse(
get() = error == null get() = error == null
open val errorCodeAndMessage: String open val errorCodeAndMessage: String
get() = "$error${errorMessage?.let { " $it" }}}" get() = "$error${errorMessage?.let { " $it" }}"
} }

View File

@ -16,11 +16,11 @@ class NativeApp {
private val client = FinTsClient(SimpleFinTsClientCallback { tanChallenge -> enterTan(tanChallenge) }) private val client = FinTsClient(SimpleFinTsClientCallback { tanChallenge -> enterTan(tanChallenge) })
fun retrieveAccountData(bankCode: String, loginName: String, password: String) { fun getAccountData(bankCode: String, loginName: String, password: String) {
retrieveAccountData(GetAccountDataParameter(bankCode, loginName, password)) getAccountData(GetAccountDataParameter(bankCode, loginName, password))
} }
fun retrieveAccountData(param: GetAccountDataParameter) { fun getAccountData(param: GetAccountDataParameter) {
val response = client.getAccountData(param) val response = client.getAccountData(param)
if (response.error != null) { if (response.error != null) {

View File

@ -0,0 +1,16 @@
package commands
import NativeApp
import net.dankito.banking.fints.model.TanMethodType
data class CommonConfig(
val app: NativeApp,
val bankCode: String,
val loginName: String,
val password: String,
val preferredTanMethods: List<TanMethodType>?,
val abortIfRequiresTan: Boolean
)

View File

@ -0,0 +1,11 @@
package commands
class ConfigNames {
companion object {
const val CommonConfig = "CommonConfig"
}
}

View File

@ -0,0 +1,36 @@
package commands
import com.github.ajalt.clikt.core.CliktCommand
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.Amount
import net.dankito.banking.fints.model.Currency
import net.dankito.banking.fints.model.Money
class TransferMoneyCommand : CliktCommand("Transfers money from your account to a recipient", name = "transfer", printHelpOnEmptyArgs = true) {
val recipientName by argument("Recipient name", "Der Name des Empfängers")
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 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.")
val config by requireObject<Map<String, Any>>()
override fun run() {
val commonConfig = config[ConfigNames.CommonConfig] as CommonConfig
val (app, bankCode, loginName, password, preferredTanMethods, abortIfRequiresTan) = commonConfig
app.transferMoney(TransferMoneyParameter(bankCode, loginName, password, null, recipientName, recipientAccountIdentifier, recipientBankIdentifier,
Money(Amount(amount), Currency.DefaultCurrencyCode), reference, false, preferredTanMethods, abortIfTanIsRequired = abortIfRequiresTan))
}
}

View File

@ -1,4 +1,8 @@
package commands
import NativeApp
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.findOrSetObject
import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.options.* import com.github.ajalt.clikt.parameters.options.*
import com.github.ajalt.clikt.parameters.types.enum import com.github.ajalt.clikt.parameters.types.enum
@ -11,7 +15,8 @@ import net.dankito.banking.client.model.parameter.RetrieveTransactions
import net.dankito.banking.fints.model.TanMethodType import net.dankito.banking.fints.model.TanMethodType
import net.dankito.utils.multiplatform.extensions.todayAtEuropeBerlin import net.dankito.utils.multiplatform.extensions.todayAtEuropeBerlin
class fints4kCommandLineInterface : CliktCommand(name = "fints", printHelpOnEmptyArgs = true) {
class fints4kCommandLineInterface : CliktCommand(name = "fints", printHelpOnEmptyArgs = true, invokeWithoutSubcommand = true) {
init { init {
versionOption("1.0.0 Alpha-10", names = setOf("-v", "--version")) versionOption("1.0.0 Alpha-10", names = setOf("-v", "--version"))
} }
@ -21,6 +26,7 @@ class fints4kCommandLineInterface : CliktCommand(name = "fints", printHelpOnEmpt
val password by argument("Passwort", "Dein Onlinebanking Passwort") val password by argument("Passwort", "Dein Onlinebanking Passwort")
// val password by option("-p", "--password", help = "Dein Onlinebanking Passwort").prompt("Passwort", hideInput = true) // val password by option("-p", "--password", help = "Dein Onlinebanking Passwort").prompt("Passwort", hideInput = true)
val retrieveBalance by option("-b", "--balance", help = "Den Kontostand abrufen. Defaults to true").flag(default = true) val retrieveBalance by option("-b", "--balance", help = "Den Kontostand abrufen. Defaults to true").flag(default = true)
val retrieveTransactions by option("-t", "--transactions", help = "Die Kontoumsätze abrufen. Default: OfLast90Days. As most banks don't afford a TAN to get transactions of last 90 days") val retrieveTransactions by option("-t", "--transactions", help = "Die Kontoumsätze abrufen. Default: OfLast90Days. As most banks don't afford a TAN to get transactions of last 90 days")
.enum<RetrieveTransactions>().default(RetrieveTransactions.OfLast90Days) .enum<RetrieveTransactions>().default(RetrieveTransactions.OfLast90Days)
@ -31,12 +37,28 @@ class fints4kCommandLineInterface : CliktCommand(name = "fints", printHelpOnEmpt
.validate { it.isNullOrBlank() || LocalDate.parse(it) != null } .validate { it.isNullOrBlank() || LocalDate.parse(it) != null }
val retrieveTransactionsForLastNDays by option("-l", "--last-n-days", help = "Retrieve transactions for last n days. If set 'retrieveTransactions' gets set to '${RetrieveTransactions.AccordingToRetrieveFromAndTo}' and 'retrieveTransactionsFrom' will be ignored.").int() val retrieveTransactionsForLastNDays by option("-l", "--last-n-days", help = "Retrieve transactions for last n days. If set 'retrieveTransactions' gets set to '${RetrieveTransactions.AccordingToRetrieveFromAndTo}' and 'retrieveTransactionsFrom' will be ignored.").int()
val preferredTanMethod by option("-m", "--tan-method", help = "Your preferred TAN methods to use if action affords a TAN. Can be repeated like '-m AppTan -m SmsTan'").enum<TanMethodType>().multiple()
val preferredTanMethods by option("-m", "--tan-method", help = "Your preferred TAN methods to use if action affords a TAN. Can be repeated like '-m AppTan -m SmsTan'").enum<TanMethodType>().multiple()
val abortIfRequiresTan by option("-a", "--abort-if-requires-tan", help = "If actions should be aborted if it affords a TAN. Defaults to false").flag(default = false) val abortIfRequiresTan by option("-a", "--abort-if-requires-tan", help = "If actions should be aborted if it affords a TAN. Defaults to false").flag(default = false)
val config by findOrSetObject { mutableMapOf<String, Any>() }
override fun run() { override fun run() {
config[ConfigNames.CommonConfig] = CommonConfig(NativeApp(), bankCode, loginName, password, preferredTanMethods, abortIfRequiresTan)
if (currentContext.invokedSubcommand == null) { // if no subcommand is selected execute default command = getAccountData()
getAccountData()
}
}
private fun getAccountData() {
val commonConfig = config[ConfigNames.CommonConfig] as CommonConfig
val (app, bankCode, loginName, password, preferredTanMethods, abortIfRequiresTan) = commonConfig
val retrieveTransactionsFromDate = when { // retrieveTransactionsForLastNDays takes precedence over retrieveTransactionsFrom val retrieveTransactionsFromDate = when { // retrieveTransactionsForLastNDays takes precedence over retrieveTransactionsFrom
retrieveTransactionsForLastNDays != null -> LocalDate.todayAtEuropeBerlin().minus(retrieveTransactionsForLastNDays!!, DateTimeUnit.DAY) retrieveTransactionsForLastNDays != null -> LocalDate.todayAtEuropeBerlin().minus(retrieveTransactionsForLastNDays!!, DateTimeUnit.DAY)
retrieveTransactionsFrom.isNullOrBlank() -> null retrieveTransactionsFrom.isNullOrBlank() -> null
@ -47,7 +69,9 @@ class fints4kCommandLineInterface : CliktCommand(name = "fints", printHelpOnEmpt
val effectiveRetrieveTransactions = if (retrieveTransactionsFromDate != null || retrieveTransactionsToDate != null) RetrieveTransactions.AccordingToRetrieveFromAndTo val effectiveRetrieveTransactions = if (retrieveTransactionsFromDate != null || retrieveTransactionsToDate != null) RetrieveTransactions.AccordingToRetrieveFromAndTo
else retrieveTransactions else retrieveTransactions
NativeApp().retrieveAccountData(GetAccountDataParameter(bankCode, loginName, password, null, retrieveBalance, effectiveRetrieveTransactions,
retrieveTransactionsFromDate, retrieveTransactionsToDate, preferredTanMethod, abortIfTanIsRequired = abortIfRequiresTan)) app.getAccountData(GetAccountDataParameter(bankCode, loginName, password, null, retrieveBalance, effectiveRetrieveTransactions,
retrieveTransactionsFromDate, retrieveTransactionsToDate, preferredTanMethods, abortIfTanIsRequired = abortIfRequiresTan))
} }
} }

View File

@ -1,4 +1,7 @@
import com.github.ajalt.clikt.core.subcommands
import commands.TransferMoneyCommand
import commands.fints4kCommandLineInterface
fun main(args: Array<String>) { fun main(args: Array<String>) {
fints4kCommandLineInterface().main(args) fints4kCommandLineInterface().subcommands(TransferMoneyCommand()).main(args)
} }