diff --git a/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt b/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt index be931132..1a07e67a 100644 --- a/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt +++ b/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt @@ -18,6 +18,9 @@ expect class BigDecimal { val isPositive: Boolean + + fun negated(): BigDecimal + fun format(countDecimalPlaces: Int): String } \ No newline at end of file diff --git a/common/src/iosMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt b/common/src/iosMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt index f4b167fb..09cb00c6 100644 --- a/common/src/iosMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt +++ b/common/src/iosMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt @@ -26,6 +26,13 @@ actual class BigDecimal(val decimal: NSDecimalNumber) : Comparable { actual val isPositive: Boolean get() = this >= Zero + + actual fun negated(): BigDecimal { + val negated = decimal.decimalNumberByMultiplyingBy(NSDecimalNumber(1.toULong(), 0, true)) + + return BigDecimal(negated) + } + actual fun format(countDecimalPlaces: Int): String { val formatter = NSNumberFormatter() diff --git a/common/src/jvmMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt b/common/src/jvmMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt index 35d2e397..80b03dc8 100644 --- a/common/src/jvmMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt +++ b/common/src/jvmMain/kotlin/net/dankito/utils/multiplatform/BigDecimal.kt @@ -29,6 +29,11 @@ actual class BigDecimal actual constructor(decimal: String) : java.math.BigDecim actual val isPositive: Boolean get() = this >= ZERO + + actual fun negated(): BigDecimal { + return BigDecimal(super.negate().toString()) + } + actual fun format(countDecimalPlaces: Int): String { return String.format("%.0${countDecimalPlaces}f", this) } diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt index 5d89a13a..ac30eebf 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt @@ -69,8 +69,12 @@ open class AccountTransactionAdapter(protected val presenter: BankingPresenter) selectedTransaction = getItem(viewHolder.adapterPosition) - menu.findItem(R.id.mnitmShowTransferMoneyDialog)?.let { mnitmShowTransferMoneyDialog -> - mnitmShowTransferMoneyDialog.isVisible = selectedTransaction?.bankAccount?.supportsTransferringMoney ?: false + val canCreateMoneyTransferFrom = selectedTransaction?.canCreateMoneyTransferFrom ?: false + + menu.findItem(R.id.mnitmNewTransferWithSameData)?.isVisible = canCreateMoneyTransferFrom + + menu.findItem(R.id.mnitmNewTransferToSameRemittee)?.let { mnitmShowTransferMoneyDialog -> + mnitmShowTransferMoneyDialog.isVisible = canCreateMoneyTransferFrom val remitteeName = selectedTransaction?.otherPartyName ?: "" diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt index ffd43cbf..7c30c40c 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt @@ -224,21 +224,22 @@ open class TransferMoneyDialog : DialogFragment() { remitteeBic = data.creditorBic if (data.amount > BigDecimal.ZERO) { - edtxtAmount.setText(AmountFormat.format(data.amount)) + edtxtAmount.setText(data.amount.toString()) } + edtxtUsage.setText(data.usage) + focusEditTextAccordingToPreselectedValues() } } protected open fun focusEditTextAccordingToPreselectedValues() { - if (edtxtRemitteeName.text.toString().trim().isNotEmpty()) { - if (edtxtRemitteeIban.text.toString().trim().isNotEmpty()) { - edtxtAmount.requestFocus() - } - else { - edtxtRemitteeIban.requestFocus() - } + when { + edtxtRemitteeName.text.toString().isBlank() -> edtxtRemitteeName.requestFocus() + edtxtRemitteeIban.text.toString().isBlank() -> edtxtRemitteeIban.requestFocus() + edtxtAmount.text.toString().isBlank() -> edtxtAmount.requestFocus() + edtxtUsage.text.toString().isBlank() -> edtxtUsage.requestFocus() + else -> edtxtUsage.requestFocus() } } diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt index 444ce94e..ce4f5447 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt @@ -15,7 +15,6 @@ import androidx.recyclerview.widget.RecyclerView import net.dankito.banking.ui.android.R import net.dankito.banking.ui.android.di.BankingComponent import net.dankito.banking.ui.android.adapter.AccountTransactionAdapter -import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.parameters.TransferMoneyData import net.dankito.banking.ui.model.responses.GetTransactionsResponse import net.dankito.banking.ui.presenter.BankingPresenter @@ -119,8 +118,12 @@ class HomeFragment : Fragment() { override fun onContextItemSelected(item: MenuItem): Boolean { when (item.itemId) { - R.id.mnitmShowTransferMoneyDialog -> { - showTransferMoneyDialog() + R.id.mnitmNewTransferToSameRemittee -> { + newTransferToSameRemittee() + return true + } + R.id.mnitmNewTransferWithSameData -> { + newTransferWithSameData() return true } } @@ -172,18 +175,16 @@ class HomeFragment : Fragment() { } - private fun showTransferMoneyDialog() { + private fun newTransferToSameRemittee() { transactionAdapter.selectedTransaction?.let { selectedTransaction -> - presenter.showTransferMoneyDialog(mapPreselectedValues(selectedTransaction)) + presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransactionWithoutAmountAndUsage(selectedTransaction)) } } - private fun mapPreselectedValues(selectedTransaction: AccountTransaction?): TransferMoneyData? { - selectedTransaction?.let { - return TransferMoneyData.fromAccountTransaction(selectedTransaction) + private fun newTransferWithSameData() { + transactionAdapter.selectedTransaction?.let { selectedTransaction -> + presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransaction(selectedTransaction)) } - - return null } diff --git a/ui/BankingAndroidApp/src/main/res/menu/context_menu_account_transactions.xml b/ui/BankingAndroidApp/src/main/res/menu/context_menu_account_transactions.xml index 1b67c36b..f94bb288 100644 --- a/ui/BankingAndroidApp/src/main/res/menu/context_menu_account_transactions.xml +++ b/ui/BankingAndroidApp/src/main/res/menu/context_menu_account_transactions.xml @@ -2,8 +2,13 @@ + + \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/res/values-de/strings.xml b/ui/BankingAndroidApp/src/main/res/values-de/strings.xml index e103214e..938577be 100644 --- a/ui/BankingAndroidApp/src/main/res/values-de/strings.xml +++ b/ui/BankingAndroidApp/src/main/res/values-de/strings.xml @@ -31,6 +31,7 @@ Kontoumsätze für \'%1$s\' konnten nicht empfangen werden.\n\nFehlermeldung Ihrer Bank:\n\n%2$s Neue Überweisung an %s + Neue Überweisung mit gleichen Daten Bank (Suche auch mittels Bankleitzahl oder Ort): Geben Sie hier die selben Werte ein wie auf Ihrer Online Banking Webseite: diff --git a/ui/BankingAndroidApp/src/main/res/values/strings.xml b/ui/BankingAndroidApp/src/main/res/values/strings.xml index 6913ae7b..a43128a2 100644 --- a/ui/BankingAndroidApp/src/main/res/values/strings.xml +++ b/ui/BankingAndroidApp/src/main/res/values/strings.xml @@ -31,6 +31,7 @@ Could not retrieve account transactions for \'%1$s\'.\n\nError message from your bank:\n\n%2$s Transfer money to %s + New transfer with same data Bank (find also by bank code or city): Enter the same values here as in your online banking portal diff --git a/ui/BankingJavaFxApp/src/main/resources/Messages.properties b/ui/BankingJavaFxApp/src/main/resources/Messages.properties index 9140ef85..fd220fc8 100755 --- a/ui/BankingJavaFxApp/src/main/resources/Messages.properties +++ b/ui/BankingJavaFxApp/src/main/resources/Messages.properties @@ -30,7 +30,8 @@ account.transactions.control.view.could.not.retrieve.account.transactions=Could account.transactions.table.column.header.value.date=Value date account.transactions.table.column.header.usage=Usage account.transactions.table.column.header.amount=Amount -account.transactions.table.context.menu.transfer.money.to=Transfer money to %s +account.transactions.table.context.menu.new.transfer.to.same.remittee=Transfer money to %s +account.transactions.table.context.menu.new.transfer.with.same.data=New transfer with same data account.transactions.table.context.menu.show.transaction.details=Show details diff --git a/ui/BankingJavaFxApp/src/main/resources/Messages_de.properties b/ui/BankingJavaFxApp/src/main/resources/Messages_de.properties index 90ce6211..5604ac56 100755 --- a/ui/BankingJavaFxApp/src/main/resources/Messages_de.properties +++ b/ui/BankingJavaFxApp/src/main/resources/Messages_de.properties @@ -30,7 +30,8 @@ account.transactions.control.view.could.not.retrieve.account.transactions=Kontou account.transactions.table.column.header.value.date=Buchungstag account.transactions.table.column.header.usage=Verwendungszweck account.transactions.table.column.header.amount=Betrag -account.transactions.table.context.menu.transfer.money.to=Neue Überweisung an %s +account.transactions.table.context.menu.new.transfer.to.same.remittee=Neue Überweisung an %s +account.transactions.table.context.menu.new.transfer.with.same.data=Neue Überweisung mit gleichen Daten account.transactions.table.context.menu.show.transaction.details=Details anzeigen diff --git a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt index 9445b0f6..7a906bb3 100644 --- a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt +++ b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt @@ -83,9 +83,13 @@ open class AccountTransactionsView(private val presenter: BankingPresenter) : Vi val contextMenu = ContextMenu() contextMenu.apply { - if (selectedItem.bankAccount.supportsTransferringMoney && selectedItem.otherPartyName.isNullOrBlank() == false) { - item(String.format(FX.messages["account.transactions.table.context.menu.transfer.money.to"], selectedItem.otherPartyName)) { - action { showTransferMoneyDialog(selectedItem) } + if (selectedItem.canCreateMoneyTransferFrom) { + item(String.format(FX.messages["account.transactions.table.context.menu.new.transfer.to.same.remittee"], selectedItem.otherPartyName)) { + action { newTransferToSameRemittee(selectedItem) } + } + + item(String.format(FX.messages["account.transactions.table.context.menu.new.transfer.with.same.data"], selectedItem.otherPartyName)) { + action { newTransferWithSameData(selectedItem) } } separator() @@ -106,7 +110,11 @@ open class AccountTransactionsView(private val presenter: BankingPresenter) : Vi // presenter.showTransactionDetailsWindow(transaction.item) } - protected open fun showTransferMoneyDialog(transaction: AccountTransaction) { + protected open fun newTransferToSameRemittee(transaction: AccountTransaction) { + presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransactionWithoutAmountAndUsage(transaction)) + } + + protected open fun newTransferWithSameData(transaction: AccountTransaction) { presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransaction(transaction)) } diff --git a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/AccountTransaction.kt b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/AccountTransaction.kt index 3553d9d6..95fae62b 100644 --- a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/AccountTransaction.kt +++ b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/AccountTransaction.kt @@ -87,6 +87,9 @@ open class AccountTransaction( open val showOtherPartyName: Boolean get() = otherPartyName.isNullOrBlank() == false /* && type != "ENTGELTABSCHLUSS" && type != "AUSZAHLUNG" */ // TODO + open val canCreateMoneyTransferFrom: Boolean + get() = otherPartyAccountId != null && bankAccount.supportsTransferringMoney + open val usage: String get() = sepaUsage ?: unparsedUsage diff --git a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/parameters/TransferMoneyData.kt b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/parameters/TransferMoneyData.kt index 33dd3241..9f336196 100644 --- a/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/parameters/TransferMoneyData.kt +++ b/ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/parameters/TransferMoneyData.kt @@ -17,7 +17,7 @@ open class TransferMoneyData( companion object { - fun fromAccountTransaction(transaction: AccountTransaction): TransferMoneyData { + fun fromAccountTransactionWithoutAmountAndUsage(transaction: AccountTransaction): TransferMoneyData { return TransferMoneyData( transaction.bankAccount, transaction.otherPartyName ?: "", @@ -28,6 +28,17 @@ open class TransferMoneyData( ) } + fun fromAccountTransaction(transaction: AccountTransaction): TransferMoneyData { + return TransferMoneyData( + transaction.bankAccount, + transaction.otherPartyName ?: "", + transaction.otherPartyAccountId ?: "", + transaction.otherPartyBankCode ?: "", + if (transaction.amount.isPositive) transaction.amount else transaction.amount.negated(), + transaction.usage + ) + } + } } \ No newline at end of file diff --git a/ui/BankingiOSApp/BankingiOSApp/Base.lproj/Localizable.strings b/ui/BankingiOSApp/BankingiOSApp/Base.lproj/Localizable.strings index 673b12f7..030f6157 100644 --- a/ui/BankingiOSApp/BankingiOSApp/Base.lproj/Localizable.strings +++ b/ui/BankingiOSApp/BankingiOSApp/Base.lproj/Localizable.strings @@ -55,7 +55,9 @@ "%@ transactions" = "%@ transactions"; "Fetch all account transactions" = "Fetch earlier transactions (requires TAN)"; + "Transfer money to %@" = "Transfer money to %@"; +"New transfer with same data" = "New transfer with same data"; "Could not fetch latest transactions" = "Could not fetch latest transactions"; "Could not fetch latest transactions for %@. Error message from your bank: %@." = "Could not fetch latest transactions for %@.\nError message from your bank:\n%@."; diff --git a/ui/BankingiOSApp/BankingiOSApp/de.lproj/Localizable.strings b/ui/BankingiOSApp/BankingiOSApp/de.lproj/Localizable.strings index eb69ba53..09924e1d 100644 --- a/ui/BankingiOSApp/BankingiOSApp/de.lproj/Localizable.strings +++ b/ui/BankingiOSApp/BankingiOSApp/de.lproj/Localizable.strings @@ -55,7 +55,9 @@ "%@ transactions" = "%@ Umsätze"; "Fetch all account transactions" = "Ältere Umsätze laden (erfordert TAN)"; + "Transfer money to %@" = "Neue Überweisung an %@"; +"New transfer with same data" = "Neue Überweisung mit gleichen Daten"; "Could not fetch latest transactions" = "Umsätze konnte nicht aktualisiert werden"; "Could not fetch latest transactions for %@. Error message from your bank: %@." = "Die Umsätze für %@ konnten nicht aktualisiert werden.\nFehlermeldung Ihrer Bank:\n%@."; diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/views/AccountTransactionListItem.swift b/ui/BankingiOSApp/BankingiOSApp/ui/views/AccountTransactionListItem.swift index b310d37f..cbd35b27 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/views/AccountTransactionListItem.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/views/AccountTransactionListItem.swift @@ -16,9 +16,6 @@ struct AccountTransactionListItem: View { private let transaction: AccountTransaction private let areMoreThanOneBanksTransactionsDisplayed: Bool - - - private var transferMoneyData: TransferMoneyData @Inject private var presenter: BankingPresenterSwift @@ -28,8 +25,6 @@ struct AccountTransactionListItem: View { self.transaction = transaction self.areMoreThanOneBanksTransactionsDisplayed = areMoreThanOneBanksTransactionsDisplayed - - self.transferMoneyData = TransferMoneyData.Companion().fromAccountTransaction(transaction: transaction) } @@ -64,14 +59,22 @@ struct AccountTransactionListItem: View { } } .contextMenu { - if transaction.otherPartyAccountId != nil && transaction.bankAccount.supportsTransferringMoney { - NavigationLink(destination: LazyView(TransferMoneyDialog(preselectedBankAccount: self.transaction.bankAccount, preselectedValues: self.transferMoneyData))) { + if transaction.canCreateMoneyTransferFrom { + NavigationLink(destination: LazyView(TransferMoneyDialog(preselectedValues: TransferMoneyData.Companion().fromAccountTransactionWithoutAmountAndUsage(transaction: self.transaction)))) { HStack { Text("Transfer money to \(transaction.otherPartyName ?? "")") Image("BankTransfer") } } + + NavigationLink(destination: LazyView(TransferMoneyDialog(preselectedValues: TransferMoneyData.Companion().fromAccountTransaction(transaction: self.transaction)))) { + HStack { + Text("New transfer with same data") + + Image("BankTransfer") + } + } } } } diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift b/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift index b4f32fb6..ece8825f 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift @@ -76,9 +76,10 @@ struct TransferMoneyDialog: View { self.showAccounts = self.accountsSupportingTransferringMoney.count > 1 } - init(preselectedBankAccount: BankAccount, preselectedValues: TransferMoneyData) { + init(preselectedValues: TransferMoneyData) { self.init() + let preselectedBankAccount = preselectedValues.account self._selectedAccountIndex = State(initialValue: accountsSupportingTransferringMoney.firstIndex(where: { account in account == preselectedBankAccount }) ?? 0) self._remitteeName = State(initialValue: preselectedValues.creditorName)