Renamed usage to reference, remittee to recipient and instant payment to real-time transfer
This commit is contained in:
parent
66feba0614
commit
bf9d406053
|
@ -8,7 +8,7 @@ However it's not a full implementation of FinTS standard but implements all comm
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Retrieving account information, balances and turnovers (Kontoumsätze und -saldo).
|
- Retrieving account information, balances and turnovers (Kontoumsätze und -saldo).
|
||||||
- Transfer money and instant payments (SEPA Überweisungen und Echtzeitüberweisung).
|
- Transfer money and real-time transfers (SEPA Überweisungen und Echtzeitüberweisung).
|
||||||
- Supports TAN methods chipTAN manual, Flickercode, QrCode and Photo (Matrix code), pushTAN, smsTAN and appTAN.
|
- Supports TAN methods chipTAN manual, Flickercode, QrCode and Photo (Matrix code), pushTAN, smsTAN and appTAN.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
|
@ -400,7 +400,7 @@ open class FinTsClient(
|
||||||
|
|
||||||
response.getFirstSegmentById<ReceivedCreditCardTransactionsAndBalance>(InstituteSegmentId.CreditCardTransactions)?.let { transactionsSegment ->
|
response.getFirstSegmentById<ReceivedCreditCardTransactionsAndBalance>(InstituteSegmentId.CreditCardTransactions)?.let { transactionsSegment ->
|
||||||
balance = Money(transactionsSegment.balance.amount, transactionsSegment.balance.currency ?: "EUR")
|
balance = Money(transactionsSegment.balance.amount, transactionsSegment.balance.currency ?: "EUR")
|
||||||
bookedTransactions.addAll(transactionsSegment.transactions.map { AccountTransaction(parameter.account, it.amount, "", it.bookingDate, it.otherPartyName, null, null, "", it.valueDate) })
|
bookedTransactions.addAll(transactionsSegment.transactions.map { AccountTransaction(parameter.account, it.amount, it.otherPartyName, it.bookingDate, it.otherPartyName, null, null, "", it.valueDate) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,7 +1138,7 @@ open class FinTsClient(
|
||||||
account.setSupportsFeature(AccountFeature.RetrieveAccountTransactions, messageBuilder.supportsGetTransactions(account))
|
account.setSupportsFeature(AccountFeature.RetrieveAccountTransactions, messageBuilder.supportsGetTransactions(account))
|
||||||
account.setSupportsFeature(AccountFeature.RetrieveBalance, messageBuilder.supportsGetBalance(account))
|
account.setSupportsFeature(AccountFeature.RetrieveBalance, messageBuilder.supportsGetBalance(account))
|
||||||
account.setSupportsFeature(AccountFeature.TransferMoney, messageBuilder.supportsBankTransfer(bank, account))
|
account.setSupportsFeature(AccountFeature.TransferMoney, messageBuilder.supportsBankTransfer(bank, account))
|
||||||
account.setSupportsFeature(AccountFeature.InstantPayment, messageBuilder.supportsSepaInstantPaymentBankTransfer(bank, account))
|
account.setSupportsFeature(AccountFeature.RealTimeTransfer, messageBuilder.supportsSepaRealTimeTransfer(bank, account))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun mapToTanMethods(tanInfo: TanInfo): List<TanMethod> {
|
protected open fun mapToTanMethods(tanInfo: TanInfo): List<TanMethod> {
|
||||||
|
|
|
@ -289,7 +289,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
||||||
|
|
||||||
open fun createBankTransferMessage(data: BankTransferData, account: AccountData, dialogContext: DialogContext): MessageBuilderResult {
|
open fun createBankTransferMessage(data: BankTransferData, account: AccountData, dialogContext: DialogContext): MessageBuilderResult {
|
||||||
|
|
||||||
val segmentId = if (data.instantPayment) CustomerSegmentId.SepaInstantPaymentBankTransfer else CustomerSegmentId.SepaBankTransfer
|
val segmentId = if (data.realTimeTransfer) CustomerSegmentId.SepaRealTimeTransfer else CustomerSegmentId.SepaBankTransfer
|
||||||
|
|
||||||
val (result, urn) = supportsBankTransferAndSepaVersion(dialogContext.bank, account, segmentId)
|
val (result, urn) = supportsBankTransferAndSepaVersion(dialogContext.bank, account, segmentId)
|
||||||
|
|
||||||
|
@ -309,8 +309,8 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
||||||
return supportsBankTransferAndSepaVersion(bank, account, CustomerSegmentId.SepaBankTransfer).first.isJobVersionSupported
|
return supportsBankTransferAndSepaVersion(bank, account, CustomerSegmentId.SepaBankTransfer).first.isJobVersionSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun supportsSepaInstantPaymentBankTransfer(bank: BankData, account: AccountData): Boolean {
|
open fun supportsSepaRealTimeTransfer(bank: BankData, account: AccountData): Boolean {
|
||||||
return supportsBankTransferAndSepaVersion(bank, account, CustomerSegmentId.SepaInstantPaymentBankTransfer).first.isJobVersionSupported
|
return supportsBankTransferAndSepaVersion(bank, account, CustomerSegmentId.SepaRealTimeTransfer).first.isJobVersionSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun supportsBankTransferAndSepaVersion(bank: BankData, account: AccountData, segmentId: CustomerSegmentId): Pair<MessageBuilderResult, String?> {
|
protected open fun supportsBankTransferAndSepaVersion(bank: BankData, account: AccountData, segmentId: CustomerSegmentId): Pair<MessageBuilderResult, String?> {
|
||||||
|
|
|
@ -25,7 +25,7 @@ enum class CustomerSegmentId(override val id: String) : ISegmentId {
|
||||||
|
|
||||||
SepaBankTransfer("HKCCS"),
|
SepaBankTransfer("HKCCS"),
|
||||||
|
|
||||||
SepaInstantPaymentBankTransfer("HKIPZ"),
|
SepaRealTimeTransfer("HKIPZ"),
|
||||||
|
|
||||||
SepaAccountInfoParameters("HKSPA") // not implemented, retrieved automatically with UPD
|
SepaAccountInfoParameters("HKSPA") // not implemented, retrieved automatically with UPD
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ package net.dankito.banking.fints.messages.segmente.implementierte.sepa
|
||||||
|
|
||||||
enum class PaymentInformationMessages(val xmlTemplate: String) {
|
enum class PaymentInformationMessages(val xmlTemplate: String) {
|
||||||
|
|
||||||
Pain_001_001_03("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Document xmlns=\"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03 pain.001.001.03.xsd\"><CstmrCdtTrfInitn><GrpHdr><MsgId>\$MessageId\$</MsgId><CreDtTm>\$CreationDateTime\$</CreDtTm><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><CtrlSum>\$Amount\$</CtrlSum><InitgPty><Nm>\$DebitorName\$</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>\$PaymentInformationId\$</PmtInfId><PmtMtd>TRF</PmtMtd><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><CtrlSum>\$Amount\$</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt>\$RequestedExecutionDate\$</ReqdExctnDt><Dbtr><Nm>\$DebitorName\$</Nm></Dbtr><DbtrAcct><Id><IBAN>\$DebitorIban\$</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BIC>\$DebitorBic\$</BIC></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><EndToEndId>NOTPROVIDED</EndToEndId></PmtId><Amt><InstdAmt Ccy=\"EUR\">\$Amount\$</InstdAmt></Amt><CdtrAgt><FinInstnId><BIC>\$CreditorBic\$</BIC></FinInstnId></CdtrAgt><Cdtr><Nm>\$CreditorName\$</Nm></Cdtr><CdtrAcct><Id><IBAN>\$CreditorIban\$</IBAN></Id></CdtrAcct><RmtInf><Ustrd>\$Usage\$</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document>"),
|
Pain_001_001_03("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Document xmlns=\"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03 pain.001.001.03.xsd\"><CstmrCdtTrfInitn><GrpHdr><MsgId>\$MessageId\$</MsgId><CreDtTm>\$CreationDateTime\$</CreDtTm><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><CtrlSum>\$Amount\$</CtrlSum><InitgPty><Nm>\$DebitorName\$</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>\$PaymentInformationId\$</PmtInfId><PmtMtd>TRF</PmtMtd><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><CtrlSum>\$Amount\$</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt>\$RequestedExecutionDate\$</ReqdExctnDt><Dbtr><Nm>\$DebitorName\$</Nm></Dbtr><DbtrAcct><Id><IBAN>\$DebitorIban\$</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BIC>\$DebitorBic\$</BIC></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><EndToEndId>NOTPROVIDED</EndToEndId></PmtId><Amt><InstdAmt Ccy=\"EUR\">\$Amount\$</InstdAmt></Amt><CdtrAgt><FinInstnId><BIC>\$RecipientBic\$</BIC></FinInstnId></CdtrAgt><Cdtr><Nm>\$RecipientName\$</Nm></Cdtr><CdtrAcct><Id><IBAN>\$RecipientIban\$</IBAN></Id></CdtrAcct><RmtInf><Ustrd>\$Reference\$</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document>"),
|
||||||
|
|
||||||
Pain_001_003_03("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Document xmlns=\"urn:iso:std:iso:20022:tech:xsd:pain.001.003.03\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:iso:std:iso:20022:tech:xsd:pain.001.003.03 pain.001.003.03.xsd\"><CstmrCdtTrfInitn><GrpHdr><MsgId>\$MessageId\$</MsgId><CreDtTm>\$CreationDateTime\$</CreDtTm><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><InitgPty><Nm>\$DebitorName\$</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>\$PaymentInformationId\$</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>true</BtchBookg><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><CtrlSum>\$Amount\$</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt>\$RequestedExecutionDate\$</ReqdExctnDt><Dbtr><Nm>\$DebitorName\$</Nm></Dbtr><DbtrAcct><Id><IBAN>\$DebitorIban\$</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BIC>\$DebitorBic\$</BIC></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><EndToEndId>NOTPROVIDED</EndToEndId></PmtId><Amt><InstdAmt Ccy=\"EUR\">\$Amount\$</InstdAmt></Amt><CdtrAgt><FinInstnId><BIC>\$CreditorBic\$</BIC></FinInstnId></CdtrAgt><Cdtr><Nm>\$CreditorName\$</Nm></Cdtr><CdtrAcct><Id><IBAN>\$CreditorIban\$</IBAN></Id></CdtrAcct><RmtInf><Ustrd>\$Usage\$</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document>")
|
Pain_001_003_03("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Document xmlns=\"urn:iso:std:iso:20022:tech:xsd:pain.001.003.03\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:iso:std:iso:20022:tech:xsd:pain.001.003.03 pain.001.003.03.xsd\"><CstmrCdtTrfInitn><GrpHdr><MsgId>\$MessageId\$</MsgId><CreDtTm>\$CreationDateTime\$</CreDtTm><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><InitgPty><Nm>\$DebitorName\$</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>\$PaymentInformationId\$</PmtInfId><PmtMtd>TRF</PmtMtd><BtchBookg>true</BtchBookg><NbOfTxs>\$NumberOfTransactions\$</NbOfTxs><CtrlSum>\$Amount\$</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf><ReqdExctnDt>\$RequestedExecutionDate\$</ReqdExctnDt><Dbtr><Nm>\$DebitorName\$</Nm></Dbtr><DbtrAcct><Id><IBAN>\$DebitorIban\$</IBAN></Id></DbtrAcct><DbtrAgt><FinInstnId><BIC>\$DebitorBic\$</BIC></FinInstnId></DbtrAgt><ChrgBr>SLEV</ChrgBr><CdtTrfTxInf><PmtId><EndToEndId>NOTPROVIDED</EndToEndId></PmtId><Amt><InstdAmt Ccy=\"EUR\">\$Amount\$</InstdAmt></Amt><CdtrAgt><FinInstnId><BIC>\$RecipientBic\$</BIC></FinInstnId></CdtrAgt><Cdtr><Nm>\$RecipientName\$</Nm></Cdtr><CdtrAcct><Id><IBAN>\$RecipientIban\$</IBAN></Id></CdtrAcct><RmtInf><Ustrd>\$Reference\$</Ustrd></RmtInf></CdtTrfTxInf></PmtInf></CstmrCdtTrfInitn></Document>")
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,11 +28,11 @@ open class SepaBankTransferBase(
|
||||||
"DebitorName" to messageCreator.convertDiacriticsAndReservedXmlCharacters(debitorName),
|
"DebitorName" to messageCreator.convertDiacriticsAndReservedXmlCharacters(debitorName),
|
||||||
"DebitorIban" to account.iban!!,
|
"DebitorIban" to account.iban!!,
|
||||||
"DebitorBic" to debitorBic,
|
"DebitorBic" to debitorBic,
|
||||||
"CreditorName" to messageCreator.convertDiacriticsAndReservedXmlCharacters(data.creditorName),
|
"RecipientName" to messageCreator.convertDiacriticsAndReservedXmlCharacters(data.recipientName),
|
||||||
"CreditorIban" to data.creditorIban.replace(" ", ""),
|
"RecipientIban" to data.recipientAccountId.replace(" ", ""),
|
||||||
"CreditorBic" to data.creditorBic.replace(" ", ""),
|
"RecipientBic" to data.recipientBankCode.replace(" ", ""),
|
||||||
"Amount" to data.amount.amount.string.replace(',', '.'), // TODO: check if ',' or '.' should be used as decimal separator
|
"Amount" to data.amount.amount.string.replace(',', '.'), // TODO: check if ',' or '.' should be used as decimal separator
|
||||||
"Usage" to if (data.usage.isEmpty()) " " else messageCreator.convertDiacriticsAndReservedXmlCharacters(data.usage),
|
"Reference" to if (data.reference.isEmpty()) " " else messageCreator.convertDiacriticsAndReservedXmlCharacters(data.reference),
|
||||||
"RequestedExecutionDate" to RequestedExecutionDateValueForNotScheduledTransfers
|
"RequestedExecutionDate" to RequestedExecutionDateValueForNotScheduledTransfers
|
||||||
),
|
),
|
||||||
messageCreator
|
messageCreator
|
||||||
|
|
|
@ -44,8 +44,8 @@ open class AccountData(
|
||||||
open val supportsTransferringMoney: Boolean
|
open val supportsTransferringMoney: Boolean
|
||||||
get() = supportsFeature(AccountFeature.TransferMoney)
|
get() = supportsFeature(AccountFeature.TransferMoney)
|
||||||
|
|
||||||
open val supportsInstantPaymentMoneyTransfer: Boolean
|
open val supportsRealTimeTransfer: Boolean
|
||||||
get() = supportsFeature(AccountFeature.InstantPayment)
|
get() = supportsFeature(AccountFeature.RealTimeTransfer)
|
||||||
|
|
||||||
|
|
||||||
open fun supportsFeature(feature: AccountFeature): Boolean {
|
open fun supportsFeature(feature: AccountFeature): Boolean {
|
||||||
|
|
|
@ -9,6 +9,6 @@ enum class AccountFeature {
|
||||||
|
|
||||||
TransferMoney,
|
TransferMoney,
|
||||||
|
|
||||||
InstantPayment
|
RealTimeTransfer
|
||||||
|
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ open class AccountTransaction(
|
||||||
val account: AccountData,
|
val account: AccountData,
|
||||||
val amount: Money,
|
val amount: Money,
|
||||||
val isReversal: Boolean,
|
val isReversal: Boolean,
|
||||||
val unparsedUsage: String,
|
val unparsedReference: String,
|
||||||
val bookingDate: Date,
|
val bookingDate: Date,
|
||||||
val otherPartyName: String?,
|
val otherPartyName: String?,
|
||||||
val otherPartyBankCode: String?,
|
val otherPartyBankCode: String?,
|
||||||
|
@ -26,10 +26,10 @@ open class AccountTransaction(
|
||||||
val originatorsIdentificationCode: String?,
|
val originatorsIdentificationCode: String?,
|
||||||
val compensationAmount: String?,
|
val compensationAmount: String?,
|
||||||
val originalAmount: String?,
|
val originalAmount: String?,
|
||||||
val sepaUsage: String?,
|
val sepaReference: String?,
|
||||||
val deviantOriginator: String?,
|
val deviantOriginator: String?,
|
||||||
val deviantRecipient: String?,
|
val deviantRecipient: String?,
|
||||||
val usageWithNoSpecialType: String?,
|
val referenceWithNoSpecialType: String?,
|
||||||
val primaNotaNumber: String?,
|
val primaNotaNumber: String?,
|
||||||
val textKeySupplement: String?,
|
val textKeySupplement: String?,
|
||||||
|
|
||||||
|
@ -46,20 +46,24 @@ open class AccountTransaction(
|
||||||
// for object deserializers
|
// for object deserializers
|
||||||
internal constructor() : this(AccountData(), Money(Amount.Zero, ""), "", Date(0), null, null, null, null, Date(0))
|
internal constructor() : this(AccountData(), Money(Amount.Zero, ""), "", Date(0), null, null, null, null, Date(0))
|
||||||
|
|
||||||
constructor(account: AccountData, amount: Money, unparsedUsage: String, bookingDate: Date, otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?, bookingText: String?, valueDate: Date)
|
constructor(account: AccountData, amount: Money, unparsedReference: String, bookingDate: Date, otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?, bookingText: String?, valueDate: Date)
|
||||||
: this(account, amount, false, unparsedUsage, bookingDate, otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate,
|
: this(account, amount, false, unparsedReference, bookingDate, otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate,
|
||||||
0, null, null, null,
|
0, null, null, null,
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null,
|
null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||||
null, "", "", null, null, "", null)
|
null, "", "", null, null, "", null)
|
||||||
|
|
||||||
|
|
||||||
|
val reference: String
|
||||||
|
get() = sepaReference ?: unparsedReference
|
||||||
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other !is AccountTransaction) return false
|
if (other !is AccountTransaction) return false
|
||||||
|
|
||||||
if (account != other.account) return false
|
if (account != other.account) return false
|
||||||
if (amount != other.amount) return false
|
if (amount != other.amount) return false
|
||||||
if (unparsedUsage != other.unparsedUsage) return false
|
if (unparsedReference != other.unparsedReference) return false
|
||||||
if (bookingDate != other.bookingDate) return false
|
if (bookingDate != other.bookingDate) return false
|
||||||
if (otherPartyName != other.otherPartyName) return false
|
if (otherPartyName != other.otherPartyName) return false
|
||||||
if (otherPartyBankCode != other.otherPartyBankCode) return false
|
if (otherPartyBankCode != other.otherPartyBankCode) return false
|
||||||
|
@ -73,7 +77,7 @@ open class AccountTransaction(
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = account.hashCode()
|
var result = account.hashCode()
|
||||||
result = 31 * result + amount.hashCode()
|
result = 31 * result + amount.hashCode()
|
||||||
result = 31 * result + unparsedUsage.hashCode()
|
result = 31 * result + unparsedReference.hashCode()
|
||||||
result = 31 * result + bookingDate.hashCode()
|
result = 31 * result + bookingDate.hashCode()
|
||||||
result = 31 * result + (otherPartyName?.hashCode() ?: 0)
|
result = 31 * result + (otherPartyName?.hashCode() ?: 0)
|
||||||
result = 31 * result + (otherPartyBankCode?.hashCode() ?: 0)
|
result = 31 * result + (otherPartyBankCode?.hashCode() ?: 0)
|
||||||
|
@ -85,7 +89,7 @@ open class AccountTransaction(
|
||||||
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "$valueDate $amount $otherPartyName: $unparsedUsage"
|
return "$valueDate $amount $otherPartyName: $unparsedReference"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,10 +2,10 @@ package net.dankito.banking.fints.model
|
||||||
|
|
||||||
|
|
||||||
open class BankTransferData(
|
open class BankTransferData(
|
||||||
val creditorName: String,
|
val recipientName: String,
|
||||||
val creditorIban: String,
|
val recipientAccountId: String,
|
||||||
val creditorBic: String,
|
val recipientBankCode: String,
|
||||||
val amount: Money,
|
val amount: Money,
|
||||||
val usage: String,
|
val reference: String,
|
||||||
val instantPayment: Boolean = false
|
val realTimeTransfer: Boolean = false
|
||||||
)
|
)
|
|
@ -306,7 +306,7 @@ open class ResponseParser(
|
||||||
parseBoolean(parametersDataElements[1]),
|
parseBoolean(parametersDataElements[1]),
|
||||||
parseBoolean(parametersDataElements[2]),
|
parseBoolean(parametersDataElements[2]),
|
||||||
if (segmentVersion >= 2) parseBoolean(parametersDataElements[3]) else false,
|
if (segmentVersion >= 2) parseBoolean(parametersDataElements[3]) else false,
|
||||||
if (segmentVersion >= 3) parseInt(parametersDataElements[4]) else SepaAccountInfoParameters.CountReservedUsageLengthNotSet,
|
if (segmentVersion >= 3) parseInt(parametersDataElements[4]) else SepaAccountInfoParameters.CountReservedReferenceLengthNotSet,
|
||||||
parametersDataElements.subList(supportedSepaFormatsBeginIndex, parametersDataElements.size)
|
parametersDataElements.subList(supportedSepaFormatsBeginIndex, parametersDataElements.size)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ open class SepaAccountInfoParameters(
|
||||||
* Über diese Information legt das Kreditinstitut fest, ob bei SEPA-Zahlungsverkehrsinstrumenten die Verwendung
|
* Über diese Information legt das Kreditinstitut fest, ob bei SEPA-Zahlungsverkehrsinstrumenten die Verwendung
|
||||||
* von strukturierten Verwendungszweckinformationen („StructuredRemittanceInformation“) erlaubt ist oder nicht.
|
* von strukturierten Verwendungszweckinformationen („StructuredRemittanceInformation“) erlaubt ist oder nicht.
|
||||||
*/
|
*/
|
||||||
val structuredUsageAllowed: Boolean,
|
val structuredReferenceAllowed: Boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kennzeichen dafür, ob die Belegung des Feldes „Maximale Anzahl Einträge“ im Kundenauftrag zugelassen ist.
|
* Kennzeichen dafür, ob die Belegung des Feldes „Maximale Anzahl Einträge“ im Kundenauftrag zugelassen ist.
|
||||||
|
@ -47,7 +47,7 @@ open class SepaAccountInfoParameters(
|
||||||
* reserviert sind. Diese Stellen dürfen vom Kundenprodukt nicht für andere Zwecke verwendet werden. Die Anzahl
|
* reserviert sind. Diese Stellen dürfen vom Kundenprodukt nicht für andere Zwecke verwendet werden. Die Anzahl
|
||||||
* wird vom Ende des letzten SEPA-Elementes aus gezählt und darf den Wert 35 nicht überschreiten.
|
* wird vom Ende des letzten SEPA-Elementes aus gezählt und darf den Wert 35 nicht überschreiten.
|
||||||
*/
|
*/
|
||||||
val countReservedUsageLength: Int,
|
val countReservedReferenceLength: Int,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dieses DE beschreibt Ort, Name und Version einer SEPA pain message als URN. Die korrekte Bezeichnung des URN
|
* Dieses DE beschreibt Ort, Name und Version einer SEPA pain message als URN. Die korrekte Bezeichnung des URN
|
||||||
|
@ -69,7 +69,7 @@ open class SepaAccountInfoParameters(
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val CountReservedUsageLengthNotSet = 0
|
const val CountReservedReferenceLengthNotSet = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -51,7 +51,7 @@ open class Mt940AccountTransactionsParser(
|
||||||
account,
|
account,
|
||||||
Money(mapAmount(transaction.statementLine), currency),
|
Money(mapAmount(transaction.statementLine), currency),
|
||||||
transaction.statementLine.isReversal,
|
transaction.statementLine.isReversal,
|
||||||
transaction.information?.unparsedUsage ?: "",
|
transaction.information?.unparsedReference ?: "",
|
||||||
transaction.statementLine.bookingDate ?: statement.closingBalance.bookingDate,
|
transaction.statementLine.bookingDate ?: statement.closingBalance.bookingDate,
|
||||||
transaction.information?.otherPartyName,
|
transaction.information?.otherPartyName,
|
||||||
transaction.information?.otherPartyBankCode,
|
transaction.information?.otherPartyBankCode,
|
||||||
|
@ -70,10 +70,10 @@ open class Mt940AccountTransactionsParser(
|
||||||
transaction.information?.originatorsIdentificationCode,
|
transaction.information?.originatorsIdentificationCode,
|
||||||
transaction.information?.compensationAmount,
|
transaction.information?.compensationAmount,
|
||||||
transaction.information?.originalAmount,
|
transaction.information?.originalAmount,
|
||||||
transaction.information?.sepaUsage,
|
transaction.information?.sepaReference,
|
||||||
transaction.information?.deviantOriginator,
|
transaction.information?.deviantOriginator,
|
||||||
transaction.information?.deviantRecipient,
|
transaction.information?.deviantRecipient,
|
||||||
transaction.information?.usageWithNoSpecialType,
|
transaction.information?.referenceWithNoSpecialType,
|
||||||
transaction.information?.primaNotaNumber,
|
transaction.information?.primaNotaNumber,
|
||||||
transaction.information?.textKeySupplement,
|
transaction.information?.textKeySupplement,
|
||||||
|
|
||||||
|
|
|
@ -56,19 +56,19 @@ open class Mt940Parser : IMt940Parser {
|
||||||
|
|
||||||
val AmountRegex = Regex("\\d+,\\d*")
|
val AmountRegex = Regex("\\d+,\\d*")
|
||||||
|
|
||||||
val UsageTypeRegex = Regex("[A-Z]{4}\\+")
|
val ReferenceTypeRegex = Regex("[A-Z]{4}\\+")
|
||||||
|
|
||||||
|
|
||||||
const val EndToEndReferenceUsageKey = "EREF+"
|
const val EndToEndReferenceKey = "EREF+"
|
||||||
const val CustomerReferenceUsageKey = "KREF+"
|
const val CustomerReferenceKey = "KREF+"
|
||||||
const val MandateReferenceUsageKey = "MREF+"
|
const val MandateReferenceKey = "MREF+"
|
||||||
const val CreditorIdentifierUsageKey = "CRED+"
|
const val CreditorIdentifierKey = "CRED+"
|
||||||
const val OriginatorsIdentificationCodeUsageKey = "DEBT+"
|
const val OriginatorsIdentificationCodeKey = "DEBT+"
|
||||||
const val CompensationAmountUsageKey = "COAM+"
|
const val CompensationAmountKey = "COAM+"
|
||||||
const val OriginalAmountUsageKey = "OAMT+"
|
const val OriginalAmountKey = "OAMT+"
|
||||||
const val SepaUsageUsageKey = "SVWZ+"
|
const val SepaReferenceKey = "SVWZ+"
|
||||||
const val DeviantOriginatorUsageKey = "ABWA+"
|
const val DeviantOriginatorKey = "ABWA+"
|
||||||
const val DeviantRecipientUsageKey = "ABWE+"
|
const val DeviantRecipientKey = "ABWE+"
|
||||||
|
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(Mt940Parser::class)
|
private val log = LoggerFactory.getLogger(Mt940Parser::class)
|
||||||
|
@ -295,7 +295,7 @@ open class Mt940Parser : IMt940Parser {
|
||||||
try {
|
try {
|
||||||
val information = parseInformationToAccountOwner(informationToAccountOwnerString)
|
val information = parseInformationToAccountOwner(informationToAccountOwnerString)
|
||||||
|
|
||||||
mapUsage(information)
|
mapReference(information)
|
||||||
|
|
||||||
return information
|
return information
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -310,7 +310,7 @@ open class Mt940Parser : IMt940Parser {
|
||||||
// see Finanzdatenformate p. 209 - 215
|
// see Finanzdatenformate p. 209 - 215
|
||||||
val geschaeftsvorfallCode = informationToAccountOwnerString.substring(0, 2) // TODO: may map
|
val geschaeftsvorfallCode = informationToAccountOwnerString.substring(0, 2) // TODO: may map
|
||||||
|
|
||||||
val usageParts = mutableListOf<String>()
|
val referenceParts = mutableListOf<String>()
|
||||||
val otherPartyName = StringBuilder()
|
val otherPartyName = StringBuilder()
|
||||||
var otherPartyBankCode: String? = null
|
var otherPartyBankCode: String? = null
|
||||||
var otherPartyAccountId: String? = null
|
var otherPartyAccountId: String? = null
|
||||||
|
@ -326,48 +326,48 @@ open class Mt940Parser : IMt940Parser {
|
||||||
when (fieldCode) {
|
when (fieldCode) {
|
||||||
0 -> bookingText = fieldValue
|
0 -> bookingText = fieldValue
|
||||||
10 -> primaNotaNumber = fieldValue
|
10 -> primaNotaNumber = fieldValue
|
||||||
in 20..29 -> usageParts.add(fieldValue)
|
in 20..29 -> referenceParts.add(fieldValue)
|
||||||
30 -> otherPartyBankCode = fieldValue
|
30 -> otherPartyBankCode = fieldValue
|
||||||
31 -> otherPartyAccountId = fieldValue
|
31 -> otherPartyAccountId = fieldValue
|
||||||
32, 33 -> otherPartyName.append(fieldValue)
|
32, 33 -> otherPartyName.append(fieldValue)
|
||||||
34 -> textKeySupplement = fieldValue
|
34 -> textKeySupplement = fieldValue
|
||||||
in 60..63 -> usageParts.add(fieldValue)
|
in 60..63 -> referenceParts.add(fieldValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val usage = if (isFormattedUsage(usageParts)) joinUsageParts(usageParts)
|
val reference = if (isFormattedReference(referenceParts)) joinReferenceParts(referenceParts)
|
||||||
else usageParts.joinToString(" ")
|
else referenceParts.joinToString(" ")
|
||||||
|
|
||||||
val otherPartyNameString = if (otherPartyName.isEmpty()) null else otherPartyName.toString()
|
val otherPartyNameString = if (otherPartyName.isEmpty()) null else otherPartyName.toString()
|
||||||
|
|
||||||
return InformationToAccountOwner(
|
return InformationToAccountOwner(
|
||||||
usage, otherPartyNameString, otherPartyBankCode, otherPartyAccountId,
|
reference, otherPartyNameString, otherPartyBankCode, otherPartyAccountId,
|
||||||
bookingText, primaNotaNumber, textKeySupplement
|
bookingText, primaNotaNumber, textKeySupplement
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun joinUsageParts(usageParts: List<String>): String {
|
protected open fun joinReferenceParts(referenceParts: List<String>): String {
|
||||||
val usage = StringBuilder()
|
val reference = StringBuilder()
|
||||||
|
|
||||||
usageParts.firstOrNull()?.let {
|
referenceParts.firstOrNull()?.let {
|
||||||
usage.append(it)
|
reference.append(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in 1..usageParts.size - 1) {
|
for (i in 1..referenceParts.size - 1) {
|
||||||
val part = usageParts[i]
|
val part = referenceParts[i]
|
||||||
if (part.isNotEmpty() && part.first().isUpperCase && usageParts[i - 1].last().isUpperCase == false) {
|
if (part.isNotEmpty() && part.first().isUpperCase && referenceParts[i - 1].last().isUpperCase == false) {
|
||||||
usage.append(" ")
|
reference.append(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
usage.append(part)
|
reference.append(part)
|
||||||
}
|
}
|
||||||
|
|
||||||
return usage.toString()
|
return reference.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun isFormattedUsage(usageParts: List<String>): Boolean {
|
protected open fun isFormattedReference(referenceParts: List<String>): Boolean {
|
||||||
return usageParts.any { UsageTypeRegex.find(it) != null }
|
return referenceParts.any { ReferenceTypeRegex.find(it) != null }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -392,53 +392,54 @@ open class Mt940Parser : IMt940Parser {
|
||||||
*
|
*
|
||||||
* Weitere 4 Verwendungszwecke können zu den Feldschlüsseln 60 bis 63 eingestellt werden.
|
* Weitere 4 Verwendungszwecke können zu den Feldschlüsseln 60 bis 63 eingestellt werden.
|
||||||
*/
|
*/
|
||||||
protected open fun mapUsage(information: InformationToAccountOwner) {
|
protected open fun mapReference(information: InformationToAccountOwner) {
|
||||||
val usageParts = getUsageParts(information.unparsedUsage)
|
val referenceParts = getReferenceParts(information.unparsedReference)
|
||||||
|
|
||||||
usageParts.forEach { entry ->
|
referenceParts.forEach { entry ->
|
||||||
setUsageLineValue(information, entry.key, entry.value)
|
setReferenceLineValue(information, entry.key, entry.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun getUsageParts(unparsedUsage: String): Map<String, String> {
|
open fun getReferenceParts(unparsedReference: String): Map<String, String> {
|
||||||
var previousMatchType = ""
|
var previousMatchType = ""
|
||||||
var previousMatchEnd = 0
|
var previousMatchEnd = 0
|
||||||
|
|
||||||
val usageParts = mutableMapOf<String, String>()
|
val referenceParts = mutableMapOf<String, String>()
|
||||||
|
|
||||||
UsageTypeRegex.findAll(unparsedUsage).forEach { matchResult ->
|
ReferenceTypeRegex.findAll(unparsedReference).forEach { matchResult ->
|
||||||
if (previousMatchEnd > 0) {
|
if (previousMatchEnd > 0) {
|
||||||
val typeValue = unparsedUsage.substring(previousMatchEnd, matchResult.range.first)
|
val typeValue = unparsedReference.substring(previousMatchEnd, matchResult.range.first)
|
||||||
|
|
||||||
usageParts[previousMatchType] = typeValue
|
referenceParts[previousMatchType] = typeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
previousMatchType = unparsedUsage.substring(matchResult.range)
|
previousMatchType = unparsedReference.substring(matchResult.range)
|
||||||
previousMatchEnd = matchResult.range.last + 1
|
previousMatchEnd = matchResult.range.last + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previousMatchEnd > 0) {
|
if (previousMatchEnd > 0) {
|
||||||
val typeValue = unparsedUsage.substring(previousMatchEnd, unparsedUsage.length)
|
val typeValue = unparsedReference.substring(previousMatchEnd, unparsedReference.length)
|
||||||
|
|
||||||
usageParts[previousMatchType] = typeValue
|
referenceParts[previousMatchType] = typeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return usageParts
|
return referenceParts
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun setUsageLineValue(information: InformationToAccountOwner, usageType: String, typeValue: String) {
|
// TODO: there are more. See .pdf from Deutsche Bank
|
||||||
when (usageType) {
|
protected open fun setReferenceLineValue(information: InformationToAccountOwner, referenceType: String, typeValue: String) {
|
||||||
EndToEndReferenceUsageKey -> information.endToEndReference = typeValue
|
when (referenceType) {
|
||||||
CustomerReferenceUsageKey -> information.customerReference = typeValue
|
EndToEndReferenceKey -> information.endToEndReference = typeValue
|
||||||
MandateReferenceUsageKey -> information.mandateReference = typeValue
|
CustomerReferenceKey -> information.customerReference = typeValue
|
||||||
CreditorIdentifierUsageKey -> information.creditorIdentifier = typeValue
|
MandateReferenceKey -> information.mandateReference = typeValue
|
||||||
OriginatorsIdentificationCodeUsageKey -> information.originatorsIdentificationCode = typeValue
|
CreditorIdentifierKey -> information.creditorIdentifier = typeValue
|
||||||
CompensationAmountUsageKey -> information.compensationAmount = typeValue
|
OriginatorsIdentificationCodeKey -> information.originatorsIdentificationCode = typeValue
|
||||||
OriginalAmountUsageKey -> information.originalAmount = typeValue
|
CompensationAmountKey -> information.compensationAmount = typeValue
|
||||||
SepaUsageUsageKey -> information.sepaUsage = typeValue
|
OriginalAmountKey -> information.originalAmount = typeValue
|
||||||
DeviantOriginatorUsageKey -> information.deviantOriginator = typeValue
|
SepaReferenceKey -> information.sepaReference = typeValue
|
||||||
DeviantRecipientUsageKey -> information.deviantRecipient = typeValue
|
DeviantOriginatorKey -> information.deviantOriginator = typeValue
|
||||||
else -> information.usageWithNoSpecialType = typeValue
|
DeviantRecipientKey -> information.deviantRecipient = typeValue
|
||||||
|
else -> information.referenceWithNoSpecialType = typeValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package net.dankito.banking.fints.transactions.mt940.model
|
||||||
|
|
||||||
|
|
||||||
open class InformationToAccountOwner(
|
open class InformationToAccountOwner(
|
||||||
val unparsedUsage: String,
|
val unparsedReference: String,
|
||||||
val otherPartyName: String?,
|
val otherPartyName: String?,
|
||||||
val otherPartyBankCode: String?,
|
val otherPartyBankCode: String?,
|
||||||
val otherPartyAccountId: String?,
|
val otherPartyAccountId: String?,
|
||||||
|
@ -25,17 +25,17 @@ open class InformationToAccountOwner(
|
||||||
|
|
||||||
var originalAmount: String? = null
|
var originalAmount: String? = null
|
||||||
|
|
||||||
var sepaUsage: String? = null
|
var sepaReference: String? = null
|
||||||
|
|
||||||
var deviantOriginator: String? = null
|
var deviantOriginator: String? = null
|
||||||
|
|
||||||
var deviantRecipient: String? = null
|
var deviantRecipient: String? = null
|
||||||
|
|
||||||
var usageWithNoSpecialType: String? = null
|
var referenceWithNoSpecialType: String? = null
|
||||||
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "$otherPartyName $unparsedUsage"
|
return "$otherPartyName $unparsedReference"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,11 +15,11 @@ class SepaBankTransferBaseTest {
|
||||||
val debitorName = "Nelson Mandela"
|
val debitorName = "Nelson Mandela"
|
||||||
val debitorIban = "ZA123456780987654321"
|
val debitorIban = "ZA123456780987654321"
|
||||||
val debitorBic = "ABCDZAEFXXX"
|
val debitorBic = "ABCDZAEFXXX"
|
||||||
val creditorName = "Mahatma Gandhi"
|
val recipientName = "Mahatma Gandhi"
|
||||||
val creditorIban = "IN123456780987654321"
|
val recipientIban = "IN123456780987654321"
|
||||||
val creditorBic = "ABCDINEFXXX"
|
val recipientBic = "ABCDINEFXXX"
|
||||||
val amount = Amount("1234,56")
|
val amount = Amount("1234,56")
|
||||||
val usage = "What should Mahatma Gandhi want with money?"
|
val reference = "What should Mahatma Gandhi want with money?"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class SepaBankTransferBaseTest {
|
||||||
debitorName,
|
debitorName,
|
||||||
AccountData("", null, 0, "", debitorIban, "", null, null, "", null, null, listOf()),
|
AccountData("", null, 0, "", debitorIban, "", null, null, "", null, null, listOf()),
|
||||||
debitorBic,
|
debitorBic,
|
||||||
BankTransferData(creditorName, creditorIban, creditorBic, Money(amount, "EUR"), usage)
|
BankTransferData(recipientName, recipientIban, recipientBic, Money(amount, "EUR"), reference)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ class SepaBankTransferBaseTest {
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result).contains(debitorName, debitorIban, debitorBic, creditorName, creditorIban, creditorBic,
|
expect(result).contains(debitorName, debitorIban, debitorBic, recipientName, recipientIban, recipientBic,
|
||||||
amount.toString().replace(',', '.'), usage, "urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.001.001.03")
|
amount.toString().replace(',', '.'), reference, "urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.001.001.03")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -55,7 +55,7 @@ class SepaBankTransferBaseTest {
|
||||||
debitorName,
|
debitorName,
|
||||||
AccountData("", null, 0, "", debitorIban, "", null, null, "", null, null, listOf()),
|
AccountData("", null, 0, "", debitorIban, "", null, null, "", null, null, listOf()),
|
||||||
debitorBic,
|
debitorBic,
|
||||||
BankTransferData(creditorName, creditorIban, creditorBic, Money(amount, "EUR"), usage)
|
BankTransferData(recipientName, recipientIban, recipientBic, Money(amount, "EUR"), reference)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,8 +64,8 @@ class SepaBankTransferBaseTest {
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result).contains(debitorName, debitorIban, debitorBic, creditorName, creditorIban, creditorBic,
|
expect(result).contains(debitorName, debitorIban, debitorBic, recipientName, recipientIban, recipientBic,
|
||||||
amount.toString().replace(',', '.'), usage, "urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.001.003.03")
|
amount.toString().replace(',', '.'), reference, "urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.001.003.03")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -558,9 +558,9 @@ class ResponseParserTest : FinTsTestBase() {
|
||||||
for (segment in sepaAccountInfoParameters) {
|
for (segment in sepaAccountInfoParameters) {
|
||||||
expect(segment.retrieveSingleAccountAllowed).isTrue()
|
expect(segment.retrieveSingleAccountAllowed).isTrue()
|
||||||
expect(segment.nationalAccountRelationshipAllowed).isFalse()
|
expect(segment.nationalAccountRelationshipAllowed).isFalse()
|
||||||
expect(segment.structuredUsageAllowed).isFalse()
|
expect(segment.structuredReferenceAllowed).isFalse()
|
||||||
expect(segment.settingMaxAllowedEntriesAllowed).isFalse()
|
expect(segment.settingMaxAllowedEntriesAllowed).isFalse()
|
||||||
expect(segment.countReservedUsageLength).toBe(SepaAccountInfoParameters.CountReservedUsageLengthNotSet)
|
expect(segment.countReservedReferenceLength).toBe(SepaAccountInfoParameters.CountReservedReferenceLengthNotSet)
|
||||||
expect(segment.supportedSepaFormats).containsExactly(
|
expect(segment.supportedSepaFormats).containsExactly(
|
||||||
"sepade.pain.001.001.02.xsd",
|
"sepade.pain.001.001.02.xsd",
|
||||||
"sepade.pain.001.002.02.xsd",
|
"sepade.pain.001.002.02.xsd",
|
||||||
|
|
|
@ -269,9 +269,9 @@ class Mt940ParserTest : FinTsTestBase() {
|
||||||
result.flatMap { it.transactions }.forEach { transaction ->
|
result.flatMap { it.transactions }.forEach { transaction ->
|
||||||
expect(transaction.information).notToBeNull()
|
expect(transaction.information).notToBeNull()
|
||||||
|
|
||||||
expect(transaction.information?.sepaUsage).notToBeNull()
|
expect(transaction.information?.sepaReference).notToBeNull()
|
||||||
|
|
||||||
if (transaction.information?.unparsedUsage?.contains("KREF+") == true) {
|
if (transaction.information?.unparsedReference?.contains("KREF+") == true) {
|
||||||
expect(transaction.information?.customerReference).notToBeNull()
|
expect(transaction.information?.customerReference).notToBeNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ open class FinTsClientTestBase {
|
||||||
val Password = "<your PIN (Online-Banking Passwort) here>"
|
val Password = "<your PIN (Online-Banking Passwort) here>"
|
||||||
|
|
||||||
|
|
||||||
val DateTimeFormatForUniqueBankTransferUsage = DateFormatter("yyyy-MM-dd'T'HH:mm:ss.SSS")
|
val DateTimeFormatForUniqueBankTransferReference = DateFormatter("yyyy-MM-dd'T'HH:mm:ss.SSS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ open class FinTsClientTestBase {
|
||||||
|
|
||||||
// transfer 1 cent to yourself. Transferring money to oneself also doesn't require to enter a TAN according to PSD2
|
// transfer 1 cent to yourself. Transferring money to oneself also doesn't require to enter a TAN according to PSD2
|
||||||
val BankTransferData = BankTransferData(Bank.customerName, account?.iban!!, Bank.bic, Money(Amount("0,01"), "EUR"),
|
val BankTransferData = BankTransferData(Bank.customerName, account?.iban!!, Bank.bic, Money(Amount("0,01"), "EUR"),
|
||||||
"${DateTimeFormatForUniqueBankTransferUsage.format(Date())} Test transaction ${UUID.random()}")
|
"${DateTimeFormatForUniqueBankTransferReference.format(Date())} Test transaction ${UUID.random()}")
|
||||||
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|
|
@ -19,7 +19,7 @@ class LuceneConfig {
|
||||||
const val BookingDateFieldName = "booking_date"
|
const val BookingDateFieldName = "booking_date"
|
||||||
const val DateSortFieldName = "value_date_sort"
|
const val DateSortFieldName = "value_date_sort"
|
||||||
|
|
||||||
const val UsageFieldName = "usage"
|
const val ReferenceFieldName = "reference"
|
||||||
|
|
||||||
const val BookingTextFieldName = "booking_text"
|
const val BookingTextFieldName = "booking_text"
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import net.dankito.banking.LuceneConfig.Companion.IdFieldName
|
||||||
import net.dankito.banking.LuceneConfig.Companion.OtherPartyAccountIdFieldName
|
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.ReferenceFieldName
|
||||||
import net.dankito.banking.ui.model.*
|
import net.dankito.banking.ui.model.*
|
||||||
import net.dankito.banking.util.ISerializer
|
import net.dankito.banking.util.ISerializer
|
||||||
import net.dankito.banking.util.JacksonJsonSerializer
|
import net.dankito.banking.util.JacksonJsonSerializer
|
||||||
|
@ -62,7 +62,7 @@ open class LuceneBankingPersistence(
|
||||||
return listOf(
|
return listOf(
|
||||||
fields.keywordField(BankAccountIdFieldName, account.technicalId),
|
fields.keywordField(BankAccountIdFieldName, account.technicalId),
|
||||||
fields.nullableFullTextSearchField(OtherPartyNameFieldName, transaction.otherPartyName, true),
|
fields.nullableFullTextSearchField(OtherPartyNameFieldName, transaction.otherPartyName, true),
|
||||||
fields.fullTextSearchField(UsageFieldName, transaction.usage, true),
|
fields.fullTextSearchField(ReferenceFieldName, transaction.reference, true),
|
||||||
fields.nullableFullTextSearchField(BookingTextFieldName, transaction.bookingText, true),
|
fields.nullableFullTextSearchField(BookingTextFieldName, transaction.bookingText, true),
|
||||||
|
|
||||||
fields.nullableStoredField(OtherPartyBankCodeFieldName, transaction.otherPartyBankCode),
|
fields.nullableStoredField(OtherPartyBankCodeFieldName, transaction.otherPartyBankCode),
|
||||||
|
|
|
@ -12,14 +12,14 @@ import net.dankito.utils.lucene.search.Searcher
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
open class LuceneRemitteeSearcher(indexFolder: File) : IRemitteeSearcher {
|
open class LuceneTransactionPartySearcher(indexFolder: File) : ITransactionPartySearcher {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val properties = listOf(
|
private val properties = listOf(
|
||||||
PropertyDescription(PropertyType.NullableString, OtherPartyNameFieldName, Remittee::name),
|
PropertyDescription(PropertyType.NullableString, OtherPartyNameFieldName, TransactionParty::name),
|
||||||
PropertyDescription(PropertyType.NullableString, OtherPartyBankCodeFieldName, Remittee::bic),
|
PropertyDescription(PropertyType.NullableString, OtherPartyBankCodeFieldName, TransactionParty::bic),
|
||||||
PropertyDescription(PropertyType.NullableString, OtherPartyAccountIdFieldName, Remittee::iban)
|
PropertyDescription(PropertyType.NullableString, OtherPartyAccountIdFieldName, TransactionParty::iban)
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,16 +30,16 @@ open class LuceneRemitteeSearcher(indexFolder: File) : IRemitteeSearcher {
|
||||||
protected val searcher = Searcher(LuceneConfig.getAccountTransactionsIndexFolder(indexFolder))
|
protected val searcher = Searcher(LuceneConfig.getAccountTransactionsIndexFolder(indexFolder))
|
||||||
|
|
||||||
|
|
||||||
override fun findRemittees(query: String): List<Remittee> {
|
override fun findTransactionParty(query: String): List<TransactionParty> {
|
||||||
val luceneQuery = queries.createQueriesForSingleTerms(query.toLowerCase()) { singleTerm ->
|
val luceneQuery = queries.createQueriesForSingleTerms(query.toLowerCase()) { singleTerm ->
|
||||||
listOf(
|
listOf(
|
||||||
queries.fulltextQuery(OtherPartyNameFieldName, singleTerm)
|
queries.fulltextQuery(OtherPartyNameFieldName, singleTerm)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return searcher.searchAndMap(MappedSearchConfig(luceneQuery, Remittee::class.java, properties))
|
return searcher.searchAndMap(MappedSearchConfig(luceneQuery, TransactionParty::class.java, properties))
|
||||||
.toSet() // don't display same Remittee multiple times
|
.toSet() // don't display same transaction party multiple times
|
||||||
.filterNot { it.iban.isNullOrBlank() || it.bic.isNullOrBlank() } // e.g. comdirect doesn't supply other party's IBAN and BIC -> filter these as they have no value for auto-entering a remittee's IBAN and BIC
|
.filterNot { it.iban.isNullOrBlank() || it.bic.isNullOrBlank() } // e.g. comdirect doesn't supply other party's IBAN and BIC -> filter these as they have no value for auto-entering a transaction party's IBAN and BIC
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ import java.util.*
|
||||||
import java.util.concurrent.ThreadLocalRandom
|
import java.util.concurrent.ThreadLocalRandom
|
||||||
|
|
||||||
|
|
||||||
class LuceneRemitteeSearcherTest {
|
class LuceneTransactionPartySearcherTest {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
private val bankingPersistence = LuceneBankingPersistence(indexFolder, databaseFolder)
|
private val bankingPersistence = LuceneBankingPersistence(indexFolder, databaseFolder)
|
||||||
|
|
||||||
private val underTest = LuceneRemitteeSearcher(indexFolder)
|
private val underTest = LuceneTransactionPartySearcher(indexFolder)
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -68,12 +68,12 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun findRemittees_ByFullName() {
|
fun findTransactionParty_ByFullName() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val query = OtherPartyName
|
val query = OtherPartyName
|
||||||
|
|
||||||
val before = underTest.findRemittees(query)
|
val before = underTest.findTransactionParty(query)
|
||||||
assertThat(before).isEmpty()
|
assertThat(before).isEmpty()
|
||||||
|
|
||||||
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
||||||
|
@ -84,7 +84,7 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.findRemittees(query)
|
val result = underTest.findTransactionParty(query)
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
@ -95,12 +95,12 @@ class LuceneRemitteeSearcherTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun findRemittees_ByPartialName() {
|
fun findTransactionParty_ByPartialName() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val query = "gand"
|
val query = "gand"
|
||||||
|
|
||||||
val before = underTest.findRemittees(query)
|
val before = underTest.findTransactionParty(query)
|
||||||
assertThat(before).isEmpty()
|
assertThat(before).isEmpty()
|
||||||
|
|
||||||
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
||||||
|
@ -111,7 +111,7 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.findRemittees(query)
|
val result = underTest.findTransactionParty(query)
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
@ -122,13 +122,13 @@ class LuceneRemitteeSearcherTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun findRemittees_SimilarNames() {
|
fun findTransactionParty_SimilarNames() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val query = "gand"
|
val query = "gand"
|
||||||
val secondOtherPartyName = "Gandalf"
|
val secondOtherPartyName = "Gandalf"
|
||||||
|
|
||||||
val before = underTest.findRemittees(query)
|
val before = underTest.findTransactionParty(query)
|
||||||
assertThat(before).isEmpty()
|
assertThat(before).isEmpty()
|
||||||
|
|
||||||
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
||||||
|
@ -139,7 +139,7 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.findRemittees(query)
|
val result = underTest.findTransactionParty(query)
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
@ -148,12 +148,12 @@ class LuceneRemitteeSearcherTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun findRemittees_DuplicateEntries() {
|
fun findTransactionParty_DuplicateEntries() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val query = OtherPartyName
|
val query = OtherPartyName
|
||||||
|
|
||||||
val before = underTest.findRemittees(query)
|
val before = underTest.findTransactionParty(query)
|
||||||
assertThat(before).isEmpty()
|
assertThat(before).isEmpty()
|
||||||
|
|
||||||
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
||||||
|
@ -166,7 +166,7 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.findRemittees(query)
|
val result = underTest.findTransactionParty(query)
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
@ -177,12 +177,12 @@ class LuceneRemitteeSearcherTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun findRemittees_OtherName() {
|
fun findTransactionParty_OtherName() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val query = "Mandela"
|
val query = "Mandela"
|
||||||
|
|
||||||
val before = underTest.findRemittees(query)
|
val before = underTest.findTransactionParty(query)
|
||||||
assertThat(before).isEmpty()
|
assertThat(before).isEmpty()
|
||||||
|
|
||||||
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf(
|
||||||
|
@ -193,7 +193,7 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.findRemittees(query)
|
val result = underTest.findTransactionParty(query)
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
@ -203,17 +203,17 @@ class LuceneRemitteeSearcherTest {
|
||||||
|
|
||||||
private fun createTransaction(bankAccount: BankAccount = bankAccountMock, bookingDate: String, amount: BigDecimal = randomBigDecimal(),
|
private fun createTransaction(bankAccount: BankAccount = bankAccountMock, bookingDate: String, amount: BigDecimal = randomBigDecimal(),
|
||||||
otherPartyName: String = randomString(), otherPartyBankCode: String = randomString(),
|
otherPartyName: String = randomString(), otherPartyBankCode: String = randomString(),
|
||||||
otherPartyAccountId: String = randomString(), usage: String = randomString()): AccountTransaction {
|
otherPartyAccountId: String = randomString(), reference: String = randomString()): AccountTransaction {
|
||||||
|
|
||||||
return createTransaction(bankAccount, dateFormat.parse(bookingDate), amount, otherPartyName,
|
return createTransaction(bankAccount, dateFormat.parse(bookingDate), amount, otherPartyName,
|
||||||
otherPartyBankCode, otherPartyAccountId, usage)
|
otherPartyBankCode, otherPartyAccountId, reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTransaction(bankAccount: BankAccount = bankAccountMock, bookingDate: Date = randomDate(), amount: BigDecimal = randomBigDecimal(),
|
private fun createTransaction(bankAccount: BankAccount = bankAccountMock, bookingDate: Date = randomDate(), amount: BigDecimal = randomBigDecimal(),
|
||||||
otherPartyName: String = randomString(), otherPartyBankCode: String = randomString(),
|
otherPartyName: String = randomString(), otherPartyBankCode: String = randomString(),
|
||||||
otherPartyAccountId: String = randomString(), usage: String = randomString()): AccountTransaction {
|
otherPartyAccountId: String = randomString(), reference: String = randomString()): AccountTransaction {
|
||||||
|
|
||||||
return AccountTransaction(bankAccount, amount.toBigDecimal(), "EUR", usage, bookingDate.toDate(), otherPartyName, otherPartyBankCode, otherPartyAccountId, null, bookingDate.toDate())
|
return AccountTransaction(bankAccount, amount.toBigDecimal(), "EUR", reference, bookingDate.toDate(), otherPartyName, otherPartyBankCode, otherPartyAccountId, null, bookingDate.toDate())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun randomString(): String {
|
private fun randomString(): String {
|
|
@ -5,8 +5,8 @@ import androidx.room.Room
|
||||||
import net.dankito.banking.persistence.dao.BaseDao
|
import net.dankito.banking.persistence.dao.BaseDao
|
||||||
import net.dankito.banking.persistence.dao.saveOrUpdate
|
import net.dankito.banking.persistence.dao.saveOrUpdate
|
||||||
import net.dankito.banking.persistence.model.*
|
import net.dankito.banking.persistence.model.*
|
||||||
import net.dankito.banking.search.IRemitteeSearcher
|
import net.dankito.banking.search.ITransactionPartySearcher
|
||||||
import net.dankito.banking.search.Remittee
|
import net.dankito.banking.search.TransactionParty
|
||||||
import net.dankito.banking.ui.model.IAccountTransaction
|
import net.dankito.banking.ui.model.IAccountTransaction
|
||||||
import net.dankito.banking.ui.model.TypedBankAccount
|
import net.dankito.banking.ui.model.TypedBankAccount
|
||||||
import net.dankito.banking.ui.model.TypedBankData
|
import net.dankito.banking.ui.model.TypedBankData
|
||||||
|
@ -18,7 +18,7 @@ import net.sqlcipher.database.SQLiteDatabase
|
||||||
import net.sqlcipher.database.SupportFactory
|
import net.sqlcipher.database.SupportFactory
|
||||||
|
|
||||||
|
|
||||||
open class RoomBankingPersistence(applicationContext: Context, password: String? = null) : IBankingPersistence, IRemitteeSearcher {
|
open class RoomBankingPersistence(applicationContext: Context, password: String? = null) : IBankingPersistence, ITransactionPartySearcher {
|
||||||
|
|
||||||
protected val db: BankingDatabase
|
protected val db: BankingDatabase
|
||||||
|
|
||||||
|
@ -154,11 +154,11 @@ open class RoomBankingPersistence(applicationContext: Context, password: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun findRemittees(query: String): List<Remittee> {
|
override fun findTransactionParty(query: String): List<TransactionParty> {
|
||||||
return db.accountTransactionDao().findRemittees(query)
|
return db.accountTransactionDao().findTransactionParty(query)
|
||||||
.toSet() // don't display same Remittee multiple times
|
.toSet() // don't display same transaction party multiple times
|
||||||
.filterNot { it.bankCode.isNullOrBlank() || it.accountId.isNullOrBlank() }
|
.filterNot { it.bankCode.isNullOrBlank() || it.accountId.isNullOrBlank() }
|
||||||
.map { Remittee(it.name, it.accountId, it.bankCode) }
|
.map { TransactionParty(it.name, it.accountId, it.bankCode) }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ package net.dankito.banking.persistence.dao
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import net.dankito.banking.persistence.model.AccountTransaction
|
import net.dankito.banking.persistence.model.AccountTransaction
|
||||||
import net.dankito.banking.persistence.model.Remittee
|
import net.dankito.banking.persistence.model.TransactionParty
|
||||||
|
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
@ -13,6 +13,6 @@ interface AccountTransactionDao : BaseDao<AccountTransaction> {
|
||||||
fun getAll(): List<AccountTransaction>
|
fun getAll(): List<AccountTransaction>
|
||||||
|
|
||||||
@Query("SELECT otherPartyName, otherPartyBankCode, otherPartyAccountId FROM AccountTransaction WHERE otherPartyName LIKE '%' || :query || '%'")
|
@Query("SELECT otherPartyName, otherPartyBankCode, otherPartyAccountId FROM AccountTransaction WHERE otherPartyName LIKE '%' || :query || '%'")
|
||||||
fun findRemittees(query: String): List<Remittee>
|
fun findTransactionParty(query: String): List<TransactionParty>
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@ open class AccountTransaction(
|
||||||
|
|
||||||
override var amount: BigDecimal,
|
override var amount: BigDecimal,
|
||||||
override var currency: String,
|
override var currency: String,
|
||||||
override var unparsedUsage: String,
|
override var unparsedReference: String,
|
||||||
override var bookingDate: Date,
|
override var bookingDate: Date,
|
||||||
override var otherPartyName: String?,
|
override var otherPartyName: String?,
|
||||||
override var otherPartyBankCode: String?,
|
override var otherPartyBankCode: String?,
|
||||||
|
@ -34,10 +34,10 @@ open class AccountTransaction(
|
||||||
override var originatorsIdentificationCode: String?,
|
override var originatorsIdentificationCode: String?,
|
||||||
override var compensationAmount: String?,
|
override var compensationAmount: String?,
|
||||||
override var originalAmount: String?,
|
override var originalAmount: String?,
|
||||||
override var sepaUsage: String?,
|
override var sepaReference: String?,
|
||||||
override var deviantOriginator: String?,
|
override var deviantOriginator: String?,
|
||||||
override var deviantRecipient: String?,
|
override var deviantRecipient: String?,
|
||||||
override var usageWithNoSpecialType: String?,
|
override var referenceWithNoSpecialType: String?,
|
||||||
override var primaNotaNumber: String?,
|
override var primaNotaNumber: String?,
|
||||||
override var textKeySupplement: String?,
|
override var textKeySupplement: String?,
|
||||||
|
|
||||||
|
@ -56,15 +56,15 @@ open class AccountTransaction(
|
||||||
|
|
||||||
/* convenience constructors for languages not supporting default values */
|
/* convenience constructors for languages not supporting default values */
|
||||||
|
|
||||||
constructor(account: BankAccount, otherPartyName: String?, unparsedUsage: String, amount: BigDecimal, valueDate: Date, bookingText: String?)
|
constructor(account: BankAccount, otherPartyName: String?, unparsedReference: String, amount: BigDecimal, valueDate: Date, bookingText: String?)
|
||||||
: this(account, amount, "EUR", unparsedUsage, valueDate,
|
: this(account, amount, "EUR", unparsedReference, valueDate,
|
||||||
otherPartyName, null, null, bookingText, valueDate)
|
otherPartyName, null, null, bookingText, valueDate)
|
||||||
|
|
||||||
|
|
||||||
constructor(account: BankAccount, amount: BigDecimal, currency: String, unparsedUsage: String, bookingDate: Date,
|
constructor(account: BankAccount, amount: BigDecimal, currency: String, unparsedReference: String, bookingDate: Date,
|
||||||
otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?,
|
otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?,
|
||||||
bookingText: String?, valueDate: Date)
|
bookingText: String?, valueDate: Date)
|
||||||
: this(account, amount, currency, unparsedUsage, bookingDate,
|
: this(account, amount, currency, unparsedReference, bookingDate,
|
||||||
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate,
|
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate,
|
||||||
0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null, null, "", null)
|
0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null, null, "", null)
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ open class BankAccount(
|
||||||
override var supportsRetrievingAccountTransactions: Boolean = false,
|
override var supportsRetrievingAccountTransactions: Boolean = false,
|
||||||
override var supportsRetrievingBalance: Boolean = false,
|
override var supportsRetrievingBalance: Boolean = false,
|
||||||
override var supportsTransferringMoney: Boolean = false,
|
override var supportsTransferringMoney: Boolean = false,
|
||||||
override var supportsInstantPaymentMoneyTransfer: Boolean = false,
|
override var supportsRealTimeTransfer: Boolean = false,
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
override var bookedTransactions: List<IAccountTransaction> = listOf(),
|
override var bookedTransactions: List<IAccountTransaction> = listOf(),
|
||||||
|
|
|
@ -26,7 +26,7 @@ open class RoomModelCreator : IModelCreator {
|
||||||
account: TypedBankAccount,
|
account: TypedBankAccount,
|
||||||
amount: BigDecimal,
|
amount: BigDecimal,
|
||||||
currency: String,
|
currency: String,
|
||||||
unparsedUsage: String,
|
unparsedReference: String,
|
||||||
bookingDate: Date,
|
bookingDate: Date,
|
||||||
otherPartyName: String?,
|
otherPartyName: String?,
|
||||||
otherPartyBankCode: String?,
|
otherPartyBankCode: String?,
|
||||||
|
@ -44,10 +44,10 @@ open class RoomModelCreator : IModelCreator {
|
||||||
originatorsIdentificationCode: String?,
|
originatorsIdentificationCode: String?,
|
||||||
compensationAmount: String?,
|
compensationAmount: String?,
|
||||||
originalAmount: String?,
|
originalAmount: String?,
|
||||||
sepaUsage: String?,
|
sepaReference: String?,
|
||||||
deviantOriginator: String?,
|
deviantOriginator: String?,
|
||||||
deviantRecipient: String?,
|
deviantRecipient: String?,
|
||||||
usageWithNoSpecialType: String?,
|
referenceWithNoSpecialType: String?,
|
||||||
primaNotaNumber: String?,
|
primaNotaNumber: String?,
|
||||||
textKeySupplement: String?,
|
textKeySupplement: String?,
|
||||||
currencyType: String?,
|
currencyType: String?,
|
||||||
|
@ -58,10 +58,10 @@ open class RoomModelCreator : IModelCreator {
|
||||||
transactionReferenceNumber: String,
|
transactionReferenceNumber: String,
|
||||||
relatedReferenceNumber: String?
|
relatedReferenceNumber: String?
|
||||||
): IAccountTransaction {
|
): IAccountTransaction {
|
||||||
return AccountTransaction(account as BankAccount, amount, currency, unparsedUsage, bookingDate, otherPartyName, otherPartyBankCode, otherPartyAccountId,
|
return AccountTransaction(account as BankAccount, amount, currency, unparsedReference, bookingDate, otherPartyName, otherPartyBankCode, otherPartyAccountId,
|
||||||
bookingText, valueDate, statementNumber, sequenceNumber, openingBalance, closingBalance, endToEndReference, customerReference, mandateReference,
|
bookingText, valueDate, statementNumber, sequenceNumber, openingBalance, closingBalance, endToEndReference, customerReference, mandateReference,
|
||||||
creditorIdentifier, originatorsIdentificationCode, compensationAmount, originalAmount, sepaUsage, deviantOriginator, deviantRecipient,
|
creditorIdentifier, originatorsIdentificationCode, compensationAmount, originalAmount, sepaReference, deviantOriginator, deviantRecipient,
|
||||||
usageWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner,
|
referenceWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner,
|
||||||
referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber)
|
referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package net.dankito.banking.persistence.model
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
|
|
||||||
|
|
||||||
data class Remittee(
|
data class TransactionParty(
|
||||||
@ColumnInfo(name = "otherPartyName") val name: String,
|
@ColumnInfo(name = "otherPartyName") val name: String,
|
||||||
|
|
||||||
@ColumnInfo(name = "otherPartyBankCode") val bankCode: String?,
|
@ColumnInfo(name = "otherPartyBankCode") val bankCode: String?,
|
|
@ -28,7 +28,7 @@ open class EntitiesModelCreator : IModelCreator {
|
||||||
account: TypedBankAccount,
|
account: TypedBankAccount,
|
||||||
amount: BigDecimal,
|
amount: BigDecimal,
|
||||||
currency: String,
|
currency: String,
|
||||||
unparsedUsage: String,
|
unparsedReference: String,
|
||||||
bookingDate: Date,
|
bookingDate: Date,
|
||||||
otherPartyName: String?,
|
otherPartyName: String?,
|
||||||
otherPartyBankCode: String?,
|
otherPartyBankCode: String?,
|
||||||
|
@ -46,10 +46,10 @@ open class EntitiesModelCreator : IModelCreator {
|
||||||
originatorsIdentificationCode: String?,
|
originatorsIdentificationCode: String?,
|
||||||
compensationAmount: String?,
|
compensationAmount: String?,
|
||||||
originalAmount: String?,
|
originalAmount: String?,
|
||||||
sepaUsage: String?,
|
sepaReference: String?,
|
||||||
deviantOriginator: String?,
|
deviantOriginator: String?,
|
||||||
deviantRecipient: String?,
|
deviantRecipient: String?,
|
||||||
usageWithNoSpecialType: String?,
|
referenceWithNoSpecialType: String?,
|
||||||
primaNotaNumber: String?,
|
primaNotaNumber: String?,
|
||||||
textKeySupplement: String?,
|
textKeySupplement: String?,
|
||||||
currencyType: String?,
|
currencyType: String?,
|
||||||
|
@ -61,11 +61,11 @@ open class EntitiesModelCreator : IModelCreator {
|
||||||
relatedReferenceNumber: String?
|
relatedReferenceNumber: String?
|
||||||
) : IAccountTransaction {
|
) : IAccountTransaction {
|
||||||
|
|
||||||
return AccountTransactionEntity(account as BankAccountEntity, amount, currency, unparsedUsage, bookingDate,
|
return AccountTransactionEntity(account as BankAccountEntity, amount, currency, unparsedReference, bookingDate,
|
||||||
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate, statementNumber, sequenceNumber,
|
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate, statementNumber, sequenceNumber,
|
||||||
openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, creditorIdentifier,
|
openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, creditorIdentifier,
|
||||||
originatorsIdentificationCode, compensationAmount, originalAmount, sepaUsage, deviantOriginator, deviantRecipient,
|
originatorsIdentificationCode, compensationAmount, originalAmount, sepaReference, deviantOriginator, deviantRecipient,
|
||||||
usageWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner,
|
referenceWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner,
|
||||||
referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber)
|
referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ open class AccountTransactionEntity(
|
||||||
override var account: BankAccountEntity,
|
override var account: BankAccountEntity,
|
||||||
override var amount: BigDecimal,
|
override var amount: BigDecimal,
|
||||||
override var currency: String,
|
override var currency: String,
|
||||||
override var unparsedUsage: String,
|
override var unparsedReference: String,
|
||||||
override var bookingDate: Date,
|
override var bookingDate: Date,
|
||||||
override var otherPartyName: String?,
|
override var otherPartyName: String?,
|
||||||
override var otherPartyBankCode: String?,
|
override var otherPartyBankCode: String?,
|
||||||
|
@ -33,10 +33,10 @@ open class AccountTransactionEntity(
|
||||||
override var originatorsIdentificationCode: String?,
|
override var originatorsIdentificationCode: String?,
|
||||||
override var compensationAmount: String?,
|
override var compensationAmount: String?,
|
||||||
override var originalAmount: String?,
|
override var originalAmount: String?,
|
||||||
override var sepaUsage: String?,
|
override var sepaReference: String?,
|
||||||
override var deviantOriginator: String?,
|
override var deviantOriginator: String?,
|
||||||
override var deviantRecipient: String?,
|
override var deviantRecipient: String?,
|
||||||
override var usageWithNoSpecialType: String?,
|
override var referenceWithNoSpecialType: String?,
|
||||||
override var primaNotaNumber: String?,
|
override var primaNotaNumber: String?,
|
||||||
override var textKeySupplement: String?,
|
override var textKeySupplement: String?,
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@ open class AccountTransactionEntity(
|
||||||
-1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null,
|
-1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null,
|
||||||
null, "", null)
|
null, "", null)
|
||||||
|
|
||||||
constructor(account: BankAccountEntity, otherPartyName: String?, unparsedUsage: String, amount: BigDecimal, valueDate: Date, bookingText: String?)
|
constructor(account: BankAccountEntity, otherPartyName: String?, unparsedReference: String, amount: BigDecimal, valueDate: Date, bookingText: String?)
|
||||||
: this(account, amount, "EUR", unparsedUsage, valueDate, otherPartyName, null, null, bookingText, valueDate, 0, null, null, null,
|
: this(account, amount, "EUR", unparsedReference, valueDate, otherPartyName, null, null, bookingText, valueDate, 0, null, null, null,
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null,
|
null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||||
null, "", "", null, null, "", null)
|
null, "", "", null, null, "", null)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ open class BankAccountEntity(
|
||||||
override var supportsRetrievingAccountTransactions: Boolean = false,
|
override var supportsRetrievingAccountTransactions: Boolean = false,
|
||||||
override var supportsRetrievingBalance: Boolean = false,
|
override var supportsRetrievingBalance: Boolean = false,
|
||||||
override var supportsTransferringMoney: Boolean = false,
|
override var supportsTransferringMoney: Boolean = false,
|
||||||
override var supportsInstantPaymentMoneyTransfer: Boolean = false,
|
override var supportsRealTimeTransfer: Boolean = false,
|
||||||
override var bookedTransactions: List<AccountTransactionEntity> = listOf(),
|
override var bookedTransactions: List<AccountTransactionEntity> = listOf(),
|
||||||
override var unbookedTransactions: List<Any> = listOf(),
|
override var unbookedTransactions: List<Any> = listOf(),
|
||||||
override var technicalId: String = UUID.random(),
|
override var technicalId: String = UUID.random(),
|
||||||
|
|
|
@ -147,7 +147,7 @@ class BankingPersistenceJsonTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTransaction(transactionIndex: Int, account: BankAccountEntity): AccountTransactionEntity {
|
private fun createTransaction(transactionIndex: Int, account: BankAccountEntity): AccountTransactionEntity {
|
||||||
return AccountTransactionEntity(account, "OtherParty_$transactionIndex", "Usage_$transactionIndex", BigDecimal(transactionIndex.toDouble()), createDate(), null)
|
return AccountTransactionEntity(account, "OtherParty_$transactionIndex", "Reference_$transactionIndex", BigDecimal(transactionIndex.toDouble()), createDate(), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDate(): Date {
|
private fun createDate(): Date {
|
||||||
|
@ -233,7 +233,7 @@ class BankingPersistenceJsonTest {
|
||||||
assertThat(deserializedTransaction.account.technicalId).isEqualTo(transaction.account.technicalId)
|
assertThat(deserializedTransaction.account.technicalId).isEqualTo(transaction.account.technicalId)
|
||||||
|
|
||||||
assertThat(deserializedTransaction.otherPartyName).isEqualTo(transaction.otherPartyName)
|
assertThat(deserializedTransaction.otherPartyName).isEqualTo(transaction.otherPartyName)
|
||||||
assertThat(deserializedTransaction.unparsedUsage).isEqualTo(transaction.unparsedUsage)
|
assertThat(deserializedTransaction.unparsedReference).isEqualTo(transaction.unparsedReference)
|
||||||
assertThat(deserializedTransaction.amount).isEqualTo(transaction.amount)
|
assertThat(deserializedTransaction.amount).isEqualTo(transaction.amount)
|
||||||
assertThat(deserializedTransaction.valueDate).isEqualTo(transaction.valueDate)
|
assertThat(deserializedTransaction.valueDate).isEqualTo(transaction.valueDate)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ open class AccountTransactionAdapter(protected val presenter: BankingPresenter)
|
||||||
val label = if (item.showOtherPartyName) item.otherPartyName else item.bookingText
|
val label = if (item.showOtherPartyName) item.otherPartyName else item.bookingText
|
||||||
viewHolder.txtvwTransactionLabel.text = label ?: item.bookingText ?: ""
|
viewHolder.txtvwTransactionLabel.text = label ?: item.bookingText ?: ""
|
||||||
|
|
||||||
viewHolder.txtvwUsage.text = item.usage
|
viewHolder.txtvwReference.text = item.reference
|
||||||
|
|
||||||
viewHolder.txtvwAmount.showAmount(presenter, item.amount)
|
viewHolder.txtvwAmount.showAmount(presenter, item.amount)
|
||||||
|
|
||||||
|
@ -66,12 +66,12 @@ open class AccountTransactionAdapter(protected val presenter: BankingPresenter)
|
||||||
|
|
||||||
menu.findItem(R.id.mnitmNewTransferWithSameData)?.isVisible = canCreateMoneyTransferFrom
|
menu.findItem(R.id.mnitmNewTransferWithSameData)?.isVisible = canCreateMoneyTransferFrom
|
||||||
|
|
||||||
menu.findItem(R.id.mnitmNewTransferToSameRemittee)?.let { mnitmShowTransferMoneyDialog ->
|
menu.findItem(R.id.mnitmNewTransferToSameTransactionParty)?.let { mnitmShowTransferMoneyDialog ->
|
||||||
mnitmShowTransferMoneyDialog.isVisible = canCreateMoneyTransferFrom
|
mnitmShowTransferMoneyDialog.isVisible = canCreateMoneyTransferFrom
|
||||||
|
|
||||||
val remitteeName = selectedTransaction?.otherPartyName ?: ""
|
val recipientName = selectedTransaction?.otherPartyName ?: ""
|
||||||
|
|
||||||
mnitmShowTransferMoneyDialog.title = view.context.getString(R.string.fragment_home_transfer_money_to, remitteeName)
|
mnitmShowTransferMoneyDialog.title = view.context.getString(R.string.fragment_home_transfer_money_to, recipientName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package net.dankito.banking.ui.android.adapter
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import net.dankito.banking.ui.android.R
|
||||||
|
import net.dankito.banking.ui.android.adapter.viewholder.RecipientViewHolder
|
||||||
|
import net.dankito.banking.search.TransactionParty
|
||||||
|
import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter
|
||||||
|
|
||||||
|
|
||||||
|
open class RecipientListAdapter(protected val itemClicked: ((TransactionParty) -> Unit)? = null) : ListRecyclerAdapter<TransactionParty, RecipientViewHolder>() {
|
||||||
|
|
||||||
|
override fun getListItemLayoutId() = R.layout.list_item_recipient
|
||||||
|
|
||||||
|
override fun createViewHolder(itemView: View): RecipientViewHolder {
|
||||||
|
return RecipientViewHolder(itemView)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindItemToView(viewHolder: RecipientViewHolder, item: TransactionParty) {
|
||||||
|
viewHolder.txtvwRecipientName.text = item.name
|
||||||
|
|
||||||
|
viewHolder.txtvwRecipientBankName.text = item.bankName
|
||||||
|
viewHolder.txtvwRecipientBankName.visibility = if (item.bankName.isNullOrBlank()) View.GONE else View.VISIBLE
|
||||||
|
|
||||||
|
viewHolder.txtvwRecipientAccountId.text = item.iban
|
||||||
|
|
||||||
|
viewHolder.txtvwRecipientBankCode.text = item.bic
|
||||||
|
|
||||||
|
viewHolder.itemView.setOnClickListener {
|
||||||
|
itemClicked?.invoke(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
package net.dankito.banking.ui.android.adapter
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import net.dankito.banking.ui.android.R
|
|
||||||
import net.dankito.banking.ui.android.adapter.viewholder.RemitteeViewHolder
|
|
||||||
import net.dankito.banking.search.Remittee
|
|
||||||
import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter
|
|
||||||
|
|
||||||
|
|
||||||
open class RemitteeListAdapter(protected val itemClicked: ((Remittee) -> Unit)? = null) : ListRecyclerAdapter<Remittee, RemitteeViewHolder>() {
|
|
||||||
|
|
||||||
override fun getListItemLayoutId() = R.layout.list_item_remittee
|
|
||||||
|
|
||||||
override fun createViewHolder(itemView: View): RemitteeViewHolder {
|
|
||||||
return RemitteeViewHolder(itemView)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun bindItemToView(viewHolder: RemitteeViewHolder, item: Remittee) {
|
|
||||||
viewHolder.txtvwRemitteeName.text = item.name
|
|
||||||
|
|
||||||
viewHolder.txtvwRemitteeBankName.text = item.bankName
|
|
||||||
viewHolder.txtvwRemitteeBankName.visibility = if (item.bankName.isNullOrBlank()) View.GONE else View.VISIBLE
|
|
||||||
|
|
||||||
viewHolder.txtvwRemitteeAccountId.text = item.iban
|
|
||||||
|
|
||||||
viewHolder.txtvwRemitteeBankCode.text = item.bic
|
|
||||||
|
|
||||||
viewHolder.itemView.setOnClickListener {
|
|
||||||
itemClicked?.invoke(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package net.dankito.banking.ui.android.adapter.presenter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.otaliastudios.autocomplete.RecyclerViewPresenter
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import net.dankito.banking.ui.android.adapter.RecipientListAdapter
|
||||||
|
import net.dankito.banking.search.TransactionParty
|
||||||
|
import net.dankito.banking.ui.android.extensions.addHorizontalItemDivider
|
||||||
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
|
|
||||||
|
|
||||||
|
open class RecipientPresenter(protected val bankingPresenter: BankingPresenter, context: Context) : RecyclerViewPresenter<TransactionParty>(context) {
|
||||||
|
|
||||||
|
protected val adapter = RecipientListAdapter { dispatchClick(it) }
|
||||||
|
|
||||||
|
protected var lastSearchRecipientJob: Job? = null
|
||||||
|
|
||||||
|
|
||||||
|
override fun instantiateAdapter(): RecyclerView.Adapter<*> {
|
||||||
|
recyclerView?.addHorizontalItemDivider()
|
||||||
|
|
||||||
|
return adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onQuery(query: CharSequence?) {
|
||||||
|
lastSearchRecipientJob?.cancel()
|
||||||
|
|
||||||
|
lastSearchRecipientJob = GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
val potentialRecipients = bankingPresenter.findRecipientsForName(query?.toString() ?: "")
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
adapter.items = potentialRecipients
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,38 +0,0 @@
|
||||||
package net.dankito.banking.ui.android.adapter.presenter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.otaliastudios.autocomplete.RecyclerViewPresenter
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import net.dankito.banking.ui.android.adapter.RemitteeListAdapter
|
|
||||||
import net.dankito.banking.search.Remittee
|
|
||||||
import net.dankito.banking.ui.android.extensions.addHorizontalItemDivider
|
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
|
||||||
|
|
||||||
|
|
||||||
open class RemitteePresenter(protected val bankingPresenter: BankingPresenter, context: Context) : RecyclerViewPresenter<Remittee>(context) {
|
|
||||||
|
|
||||||
protected val adapter = RemitteeListAdapter { dispatchClick(it) }
|
|
||||||
|
|
||||||
protected var lastSearchRemitteeJob: Job? = null
|
|
||||||
|
|
||||||
|
|
||||||
override fun instantiateAdapter(): RecyclerView.Adapter<*> {
|
|
||||||
recyclerView?.addHorizontalItemDivider()
|
|
||||||
|
|
||||||
return adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQuery(query: CharSequence?) {
|
|
||||||
lastSearchRemitteeJob?.cancel()
|
|
||||||
|
|
||||||
lastSearchRemitteeJob = GlobalScope.launch(Dispatchers.IO) {
|
|
||||||
val potentialRemittees = bankingPresenter.findRemitteesForName(query?.toString() ?: "")
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
adapter.items = potentialRemittees
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -13,7 +13,7 @@ open class AccountTransactionViewHolder(itemView: View) : RecyclerView.ViewHolde
|
||||||
|
|
||||||
val txtvwTransactionLabel: TextView = itemView.txtvwTransactionLabel
|
val txtvwTransactionLabel: TextView = itemView.txtvwTransactionLabel
|
||||||
|
|
||||||
val txtvwUsage: TextView = itemView.txtvwUsage
|
val txtvwReference: TextView = itemView.txtvwReference
|
||||||
|
|
||||||
val txtvwAmount: TextView = itemView.txtvwAmount
|
val txtvwAmount: TextView = itemView.txtvwAmount
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package net.dankito.banking.ui.android.adapter.viewholder
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kotlinx.android.synthetic.main.list_item_recipient.view.*
|
||||||
|
|
||||||
|
|
||||||
|
open class RecipientViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
|
val txtvwRecipientName: TextView = itemView.txtvwRecipientName
|
||||||
|
|
||||||
|
val txtvwRecipientBankName: TextView = itemView.txtvwRecipientBankName
|
||||||
|
|
||||||
|
val txtvwRecipientAccountId: TextView = itemView.txtvwRecipientAccountId
|
||||||
|
|
||||||
|
val txtvwRecipientBankCode: TextView = itemView.txtvwRecipientBankCode
|
||||||
|
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
package net.dankito.banking.ui.android.adapter.viewholder
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import kotlinx.android.synthetic.main.list_item_remittee.view.*
|
|
||||||
|
|
||||||
|
|
||||||
open class RemitteeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
|
||||||
|
|
||||||
val txtvwRemitteeName: TextView = itemView.txtvwRemitteeName
|
|
||||||
|
|
||||||
val txtvwRemitteeBankName: TextView = itemView.txtvwRemitteeBankName
|
|
||||||
|
|
||||||
val txtvwRemitteeAccountId: TextView = itemView.txtvwRemitteeAccountId
|
|
||||||
|
|
||||||
val txtvwRemitteeBankCode: TextView = itemView.txtvwRemitteeBankCode
|
|
||||||
|
|
||||||
}
|
|
|
@ -9,8 +9,7 @@ import net.dankito.banking.ui.android.RouterAndroid
|
||||||
import net.dankito.banking.ui.android.util.CurrentActivityTracker
|
import net.dankito.banking.ui.android.util.CurrentActivityTracker
|
||||||
import net.dankito.banking.fints4kBankingClientCreator
|
import net.dankito.banking.fints4kBankingClientCreator
|
||||||
import net.dankito.banking.persistence.IBankingPersistence
|
import net.dankito.banking.persistence.IBankingPersistence
|
||||||
import net.dankito.banking.search.IRemitteeSearcher
|
import net.dankito.banking.search.ITransactionPartySearcher
|
||||||
import net.dankito.banking.search.LuceneRemitteeSearcher
|
|
||||||
import net.dankito.banking.ui.IBankingClientCreator
|
import net.dankito.banking.ui.IBankingClientCreator
|
||||||
import net.dankito.banking.ui.IRouter
|
import net.dankito.banking.ui.IRouter
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
|
@ -88,11 +87,11 @@ class BankingModule(private val applicationContext: Context) {
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder,
|
fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder,
|
||||||
@Named(DataFolderKey) dataFolder: File,
|
@Named(DataFolderKey) dataFolder: File,
|
||||||
persister: IBankingPersistence, remitteeSearcher: IRemitteeSearcher, bankIconFinder: IBankIconFinder,
|
persister: IBankingPersistence, transactionPartySearcher: ITransactionPartySearcher, bankIconFinder: IBankIconFinder,
|
||||||
textExtractorRegistry: ITextExtractorRegistry, router: IRouter, invoiceDataExtractor: IInvoiceDataExtractor,
|
textExtractorRegistry: ITextExtractorRegistry, router: IRouter, invoiceDataExtractor: IInvoiceDataExtractor,
|
||||||
modelCreator: IModelCreator, serializer: ISerializer, asyncRunner: IAsyncRunner) : BankingPresenter {
|
modelCreator: IModelCreator, serializer: ISerializer, asyncRunner: IAsyncRunner) : BankingPresenter {
|
||||||
return BankingPresenter(bankingClientCreator, bankFinder, dataFolder, persister, router, modelCreator,
|
return BankingPresenter(bankingClientCreator, bankFinder, dataFolder, persister, router, modelCreator,
|
||||||
remitteeSearcher, bankIconFinder, textExtractorRegistry, invoiceDataExtractor, serializer, asyncRunner)
|
transactionPartySearcher, bankIconFinder, textExtractorRegistry, invoiceDataExtractor, serializer, asyncRunner)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -121,7 +120,7 @@ class BankingModule(private val applicationContext: Context) {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideRemitteeSearcher(bankingPersistence: IBankingPersistence) : IRemitteeSearcher {
|
fun provideTransactionPartySearcher(bankingPersistence: IBankingPersistence) : ITransactionPartySearcher {
|
||||||
return bankingPersistence as RoomBankingPersistence
|
return bankingPersistence as RoomBankingPersistence
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@ import kotlinx.android.synthetic.main.dialog_transfer_money.view.*
|
||||||
import net.dankito.banking.ui.android.R
|
import net.dankito.banking.ui.android.R
|
||||||
import net.dankito.banking.ui.android.di.BankingComponent
|
import net.dankito.banking.ui.android.di.BankingComponent
|
||||||
import net.dankito.banking.ui.android.adapter.BankAccountsAdapter
|
import net.dankito.banking.ui.android.adapter.BankAccountsAdapter
|
||||||
import net.dankito.banking.ui.android.adapter.presenter.RemitteePresenter
|
import net.dankito.banking.ui.android.adapter.presenter.RecipientPresenter
|
||||||
import net.dankito.banking.ui.android.extensions.addEnterPressedListener
|
import net.dankito.banking.ui.android.extensions.addEnterPressedListener
|
||||||
import net.dankito.banking.ui.android.extensions.closePopupOnBackButtonPress
|
import net.dankito.banking.ui.android.extensions.closePopupOnBackButtonPress
|
||||||
import net.dankito.banking.ui.android.listener.ListItemSelectedListener
|
import net.dankito.banking.ui.android.listener.ListItemSelectedListener
|
||||||
import net.dankito.banking.ui.android.util.StandardAutocompleteCallback
|
import net.dankito.banking.ui.android.util.StandardAutocompleteCallback
|
||||||
import net.dankito.banking.ui.android.util.StandardTextWatcher
|
import net.dankito.banking.ui.android.util.StandardTextWatcher
|
||||||
import net.dankito.banking.search.Remittee
|
import net.dankito.banking.search.TransactionParty
|
||||||
import net.dankito.banking.ui.model.TypedBankAccount
|
import net.dankito.banking.ui.model.TypedBankAccount
|
||||||
import net.dankito.banking.ui.model.parameters.TransferMoneyData
|
import net.dankito.banking.ui.model.parameters.TransferMoneyData
|
||||||
import net.dankito.banking.ui.model.responses.BankingClientResponse
|
import net.dankito.banking.ui.model.responses.BankingClientResponse
|
||||||
|
@ -60,16 +60,16 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
protected val inputValidator = InputValidator() // TODO: move to presenter
|
protected val inputValidator = InputValidator() // TODO: move to presenter
|
||||||
|
|
||||||
|
|
||||||
protected var remitteeBic: String? = null
|
protected var recipientBic: String? = null
|
||||||
|
|
||||||
|
|
||||||
protected var validRemitteeNameEntered = false
|
protected var validRecipientNameEntered = false
|
||||||
|
|
||||||
protected var validRemitteeIbanEntered = false
|
protected var validRecipientIbanEntered = false
|
||||||
|
|
||||||
protected var validRemitteeBicEntered = false
|
protected var validRecipientBicEntered = false
|
||||||
|
|
||||||
protected var validUsageEntered = true
|
protected var validReferenceEntered = true
|
||||||
|
|
||||||
protected var validAmountEntered = false
|
protected var validAmountEntered = false
|
||||||
|
|
||||||
|
@ -118,73 +118,73 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
rootView.spnBankAccounts.adapter = adapter
|
rootView.spnBankAccounts.adapter = adapter
|
||||||
rootView.spnBankAccounts.onItemSelectedListener = ListItemSelectedListener(adapter) { selectedBankAccount ->
|
rootView.spnBankAccounts.onItemSelectedListener = ListItemSelectedListener(adapter) { selectedBankAccount ->
|
||||||
this.account = selectedBankAccount
|
this.account = selectedBankAccount
|
||||||
setInstantPaymentControlsVisibility(rootView)
|
setRealTimeTransferControlsVisibility(rootView)
|
||||||
}
|
}
|
||||||
preselectedValues?.account?.let { rootView.spnBankAccounts.setSelection(adapter.getItems().indexOf(it)) }
|
preselectedValues?.account?.let { rootView.spnBankAccounts.setSelection(adapter.getItems().indexOf(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
initRemitteeAutocompletion(rootView.edtxtRemitteeName)
|
initRecipientAutocompletion(rootView.edtxtRecipientName)
|
||||||
|
|
||||||
rootView.edtxtRemitteeName.addTextChangedListener(checkRequiredDataWatcher {
|
rootView.edtxtRecipientName.addTextChangedListener(checkRequiredDataWatcher {
|
||||||
checkIfEnteredRemitteeNameIsValidWhileUserIsTyping()
|
checkIfEnteredRecipientNameIsValidWhileUserIsTyping()
|
||||||
})
|
})
|
||||||
|
|
||||||
rootView.edtxtRemitteeIban.addTextChangedListener(StandardTextWatcher {
|
rootView.edtxtRecipientIban.addTextChangedListener(StandardTextWatcher {
|
||||||
checkIfEnteredRemitteeIbanIsValidWhileUserIsTyping()
|
checkIfEnteredRecipientIbanIsValidWhileUserIsTyping()
|
||||||
tryToGetBicFromIban(it)
|
tryToGetBicFromIban(it)
|
||||||
})
|
})
|
||||||
|
|
||||||
rootView.edtxtAmount.addTextChangedListener(checkRequiredDataWatcher {
|
rootView.edtxtAmount.addTextChangedListener(checkRequiredDataWatcher {
|
||||||
checkIfEnteredAmountIsValid()
|
checkIfEnteredAmountIsValid()
|
||||||
})
|
})
|
||||||
rootView.edtxtUsage.addTextChangedListener(checkRequiredDataWatcher {
|
rootView.edtxtReference.addTextChangedListener(checkRequiredDataWatcher {
|
||||||
checkIfEnteredUsageTextIsValid()
|
checkIfEnteredReferenceTextIsValid()
|
||||||
})
|
})
|
||||||
|
|
||||||
rootView.edtxtRemitteeName.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredRemitteeNameIsValidAfterFocusLost() }
|
rootView.edtxtRecipientName.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredRecipientNameIsValidAfterFocusLost() }
|
||||||
rootView.edtxtRemitteeIban.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredRemitteeIbanIsValidAfterFocusLost() }
|
rootView.edtxtRecipientIban.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredRecipientIbanIsValidAfterFocusLost() }
|
||||||
rootView.edtxtAmount.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredAmountIsValid() }
|
rootView.edtxtAmount.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredAmountIsValid() }
|
||||||
rootView.edtxtUsage.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredUsageTextIsValid() }
|
rootView.edtxtReference.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredReferenceTextIsValid() }
|
||||||
|
|
||||||
transferMoneyIfEnterPressed(rootView.edtxtRemitteeName)
|
transferMoneyIfEnterPressed(rootView.edtxtRecipientName)
|
||||||
transferMoneyIfEnterPressed(rootView.edtxtRemitteeIban)
|
transferMoneyIfEnterPressed(rootView.edtxtRecipientIban)
|
||||||
transferMoneyIfEnterPressed(rootView.edtxtAmount)
|
transferMoneyIfEnterPressed(rootView.edtxtAmount)
|
||||||
transferMoneyIfEnterPressed(rootView.edtxtUsage)
|
transferMoneyIfEnterPressed(rootView.edtxtReference)
|
||||||
|
|
||||||
// fix that even in Locales using ',' as decimal separator entering ',' is not allowed (thanks dstibbe! https://stackoverflow.com/a/34256139)
|
// fix that even in Locales using ',' as decimal separator entering ',' is not allowed (thanks dstibbe! https://stackoverflow.com/a/34256139)
|
||||||
val decimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator()
|
val decimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator()
|
||||||
rootView.edtxtAmount.keyListener = DigitsKeyListener.getInstance("0123456789$decimalSeparator")
|
rootView.edtxtAmount.keyListener = DigitsKeyListener.getInstance("0123456789$decimalSeparator")
|
||||||
|
|
||||||
rootView.btnShowInstantPaymentInfo.setOnClickListener { showInstantPaymentInfo(rootView.btnShowInstantPaymentInfo, rootView) }
|
rootView.btnShowRealTimeTransferInfo.setOnClickListener { showRealTimeTransferInfo(rootView.btnShowRealTimeTransferInfo, rootView) }
|
||||||
|
|
||||||
setInstantPaymentControlsVisibility(rootView)
|
setRealTimeTransferControlsVisibility(rootView)
|
||||||
|
|
||||||
rootView.btnCancel.setOnClickListener { dismiss() }
|
rootView.btnCancel.setOnClickListener { dismiss() }
|
||||||
|
|
||||||
rootView.btnTransferMoney.setOnClickListener { transferMoney() }
|
rootView.btnTransferMoney.setOnClickListener { transferMoney() }
|
||||||
|
|
||||||
adjustCheckBoxInstantPaymentWidth()
|
adjustCheckBoxRealTimeTransferWidth()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open fun adjustCheckBoxInstantPaymentWidth() {
|
protected open fun adjustCheckBoxRealTimeTransferWidth() {
|
||||||
// wait some time till CheckBox is layout and lineCount is set
|
// wait some time till CheckBox is layout and lineCount is set
|
||||||
val timer = Timer()
|
val timer = Timer()
|
||||||
timer.schedule(10) { requireActivity().runOnUiThread { adjustCheckBoxInstantPaymentWidthOnUiThread() }}
|
timer.schedule(10) { requireActivity().runOnUiThread { adjustCheckBoxRealTimeTransferWidthOnUiThread() }}
|
||||||
timer.schedule(2500) { requireActivity().runOnUiThread { adjustCheckBoxInstantPaymentWidthOnUiThread() }}
|
timer.schedule(2500) { requireActivity().runOnUiThread { adjustCheckBoxRealTimeTransferWidthOnUiThread() }}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun adjustCheckBoxInstantPaymentWidthOnUiThread() {
|
protected open fun adjustCheckBoxRealTimeTransferWidthOnUiThread() {
|
||||||
if (chkbxInstantPayment.isEllipsized == false) {
|
if (chkbxRealTimeTransfer.isEllipsized == false) {
|
||||||
// by default chkbxInstantPayment uses full width, even though if its text doesn't need this space -> there
|
// by default chkbxRealTimeTransfer uses full width, even though if its text doesn't need this space -> there
|
||||||
chkbxInstantPayment.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 0f)
|
chkbxRealTimeTransfer.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 0f)
|
||||||
chkbxInstantPayment.requestLayout()
|
chkbxRealTimeTransfer.requestLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun setInstantPaymentControlsVisibility(rootView: View) {
|
protected open fun setRealTimeTransferControlsVisibility(rootView: View) {
|
||||||
rootView.lytInstantPayment.visibility =
|
rootView.lytRealTimeTransfer.visibility =
|
||||||
if (account.supportsInstantPaymentMoneyTransfer) {
|
if (account.supportsRealTimeTransfer) {
|
||||||
View.VISIBLE
|
View.VISIBLE
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -192,9 +192,9 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun showInstantPaymentInfo(btnShowInstantPaymentInfo: ImageButton, rootView: View) {
|
protected open fun showRealTimeTransferInfo(btnShowRealTimeTransferInfo: ImageButton, rootView: View) {
|
||||||
requireActivity().layoutInflater.inflate(R.layout.view_instant_payment_info, null)?.let { contentView ->
|
requireActivity().layoutInflater.inflate(R.layout.view_real_time_transfer_info, null)?.let { contentView ->
|
||||||
requireContext().hideKeyboard(lytInstantPayment)
|
requireContext().hideKeyboard(lytRealTimeTransfer)
|
||||||
|
|
||||||
val popupWindow = PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
val popupWindow = PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
|
||||||
|
@ -203,9 +203,9 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
|
|
||||||
contentView.findViewById<Button>(R.id.btnDismissPopup)?.setOnClickListener { popupWindow.dismiss() }
|
contentView.findViewById<Button>(R.id.btnDismissPopup)?.setOnClickListener { popupWindow.dismiss() }
|
||||||
|
|
||||||
popupWindow.showAtLocation(btnShowInstantPaymentInfo, Gravity.TOP, 0, 0)
|
popupWindow.showAtLocation(btnShowRealTimeTransferInfo, Gravity.TOP, 0, 0)
|
||||||
|
|
||||||
popupWindow.showAsDropDown(btnShowInstantPaymentInfo)
|
popupWindow.showAsDropDown(btnShowRealTimeTransferInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,17 +223,17 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
|
|
||||||
private fun isRequiredDataEntered() = btnTransferMoney.isEnabled
|
private fun isRequiredDataEntered() = btnTransferMoney.isEnabled
|
||||||
|
|
||||||
private fun initRemitteeAutocompletion(edtxtRemitteeName: EditText) {
|
private fun initRecipientAutocompletion(edtxtRecipientName: EditText) {
|
||||||
val autocompleteCallback = StandardAutocompleteCallback<Remittee> { _, item ->
|
val autocompleteCallback = StandardAutocompleteCallback<TransactionParty> { _, item ->
|
||||||
remitteeSelected(item)
|
recipientSelected(item)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
Autocomplete.on<Remittee>(edtxtRemitteeName)
|
Autocomplete.on<TransactionParty>(edtxtRecipientName)
|
||||||
.with(6f)
|
.with(6f)
|
||||||
.with(ColorDrawable(Color.WHITE))
|
.with(ColorDrawable(Color.WHITE))
|
||||||
.with(autocompleteCallback)
|
.with(autocompleteCallback)
|
||||||
.with(RemitteePresenter(presenter, edtxtRemitteeName.context))
|
.with(RecipientPresenter(presenter, edtxtRecipientName.context))
|
||||||
.build()
|
.build()
|
||||||
.closePopupOnBackButtonPress(dialog)
|
.closePopupOnBackButtonPress(dialog)
|
||||||
}
|
}
|
||||||
|
@ -244,8 +244,8 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
|
|
||||||
setPreselectedValues()
|
setPreselectedValues()
|
||||||
|
|
||||||
if (remitteeBic != null) {
|
if (recipientBic != null) {
|
||||||
tryToGetBicFromIban(edtxtRemitteeIban.text.toString())
|
tryToGetBicFromIban(edtxtRecipientIban.text.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,20 +254,20 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
preselectedValues?.let { data ->
|
preselectedValues?.let { data ->
|
||||||
preselectedValues = null
|
preselectedValues = null
|
||||||
|
|
||||||
edtxtRemitteeName.setText(data.creditorName)
|
edtxtRecipientName.setText(data.recipientName)
|
||||||
|
|
||||||
if (data.creditorIban.isNotBlank()) { // set only if creditorIban has a value as otherwise creditorBic would be overridden by empty search result
|
if (data.recipientAccountId.isNotBlank()) { // set only if recipientAccountId has a value as otherwise recipientBankCode would be overridden by empty search result
|
||||||
edtxtRemitteeIban.setText(data.creditorIban)
|
edtxtRecipientIban.setText(data.recipientAccountId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// a little bit inconsistent as if IBAN is not set bank's name won't be displayed even though it can be retrieved by BIC
|
// a little bit inconsistent as if IBAN is not set bank's name won't be displayed even though it can be retrieved by BIC
|
||||||
remitteeBic = data.creditorBic
|
recipientBic = data.recipientBankCode
|
||||||
|
|
||||||
if (data.amount > BigDecimal.ZERO) {
|
if (data.amount > BigDecimal.ZERO) {
|
||||||
edtxtAmount.setText(data.amount.toString())
|
edtxtAmount.setText(data.amount.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
edtxtUsage.setText(data.usage)
|
edtxtReference.setText(data.reference)
|
||||||
|
|
||||||
focusEditTextAccordingToPreselectedValues()
|
focusEditTextAccordingToPreselectedValues()
|
||||||
}
|
}
|
||||||
|
@ -275,19 +275,19 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
|
|
||||||
protected open fun focusEditTextAccordingToPreselectedValues() {
|
protected open fun focusEditTextAccordingToPreselectedValues() {
|
||||||
when {
|
when {
|
||||||
edtxtRemitteeName.text.toString().isBlank() -> edtxtRemitteeName.requestFocus()
|
edtxtRecipientName.text.toString().isBlank() -> edtxtRecipientName.requestFocus()
|
||||||
edtxtRemitteeIban.text.toString().isBlank() -> edtxtRemitteeIban.requestFocus()
|
edtxtRecipientIban.text.toString().isBlank() -> edtxtRecipientIban.requestFocus()
|
||||||
edtxtAmount.text.toString().isBlank() -> edtxtAmount.requestFocus()
|
edtxtAmount.text.toString().isBlank() -> edtxtAmount.requestFocus()
|
||||||
edtxtUsage.text.toString().isBlank() -> edtxtUsage.requestFocus()
|
edtxtReference.text.toString().isBlank() -> edtxtReference.requestFocus()
|
||||||
else -> edtxtUsage.requestFocus()
|
else -> edtxtReference.requestFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open fun remitteeSelected(item: Remittee) {
|
protected open fun recipientSelected(item: TransactionParty) {
|
||||||
edtxtRemitteeName.setText(item.name)
|
edtxtRecipientName.setText(item.name)
|
||||||
edtxtRemitteeIban.setText(item.iban)
|
edtxtRecipientIban.setText(item.iban)
|
||||||
remitteeBic = item.bic
|
recipientBic = item.bic
|
||||||
|
|
||||||
focusEditTextAccordingToPreselectedValues()
|
focusEditTextAccordingToPreselectedValues()
|
||||||
}
|
}
|
||||||
|
@ -296,12 +296,12 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
getEnteredAmount()?.let { amount -> // should only come at this stage when a valid amount has been entered
|
getEnteredAmount()?.let { amount -> // should only come at this stage when a valid amount has been entered
|
||||||
val data = TransferMoneyData(
|
val data = TransferMoneyData(
|
||||||
account,
|
account,
|
||||||
inputValidator.convertToAllowedSepaCharacters(edtxtRemitteeName.text.toString()),
|
inputValidator.convertToAllowedSepaCharacters(edtxtRecipientName.text.toString()),
|
||||||
edtxtRemitteeIban.text.toString().replace(" ", ""),
|
edtxtRecipientIban.text.toString().replace(" ", ""),
|
||||||
remitteeBic?.replace(" ", "") ?: "", // should always be != null at this point
|
recipientBic?.replace(" ", "") ?: "", // should always be != null at this point
|
||||||
amount.toBigDecimal(),
|
amount.toBigDecimal(),
|
||||||
inputValidator.convertToAllowedSepaCharacters(edtxtUsage.text.toString()),
|
inputValidator.convertToAllowedSepaCharacters(edtxtReference.text.toString()),
|
||||||
chkbxInstantPayment.isChecked
|
chkbxRealTimeTransfer.isChecked
|
||||||
)
|
)
|
||||||
|
|
||||||
presenter.transferMoneyAsync(data) {
|
presenter.transferMoneyAsync(data) {
|
||||||
|
@ -317,11 +317,11 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
if (response.userCancelledAction == false) {
|
if (response.userCancelledAction == false) {
|
||||||
val message = if (response.successful) {
|
val message = if (response.successful) {
|
||||||
context.getString(R.string.dialog_transfer_money_message_transfer_successful,
|
context.getString(R.string.dialog_transfer_money_message_transfer_successful,
|
||||||
String.format("%.02f", transferData.amount), "€", transferData.creditorName) // TODO: where to get currency from?
|
String.format("%.02f", transferData.amount), "€", transferData.recipientName) // TODO: where to get currency from?
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
context.getString(R.string.dialog_transfer_money_message_transfer_failed,
|
context.getString(R.string.dialog_transfer_money_message_transfer_failed,
|
||||||
String.format("%.02f", transferData.amount), "€", transferData.creditorName, // TODO: where to get currency from?
|
String.format("%.02f", transferData.amount), "€", transferData.recipientName, // TODO: where to get currency from?
|
||||||
response.errorToShowToUser
|
response.errorToShowToUser
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -356,66 +356,66 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showValuesForFoundBankOnUiThread(enteredIban: CharSequence, foundBank: BankInfo?) {
|
private fun showValuesForFoundBankOnUiThread(enteredIban: CharSequence, foundBank: BankInfo?) {
|
||||||
validRemitteeBicEntered = foundBank != null
|
validRecipientBicEntered = foundBank != null
|
||||||
remitteeBic = foundBank?.bic
|
recipientBic = foundBank?.bic
|
||||||
|
|
||||||
if (foundBank != null) {
|
if (foundBank != null) {
|
||||||
txtRemitteeBankInfo.text = getString(R.string.dialog_transfer_money_bic_detected_from_iban, foundBank.bic, foundBank.name)
|
txtRecipientBankInfo.text = getString(R.string.dialog_transfer_money_bic_detected_from_iban, foundBank.bic, foundBank.name)
|
||||||
txtRemitteeBankInfo.visibility = View.VISIBLE
|
txtRecipientBankInfo.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
else if (enteredIban.length >= InputValidator.MinimumLengthToDetermineBicFromIban) {
|
else if (enteredIban.length >= InputValidator.MinimumLengthToDetermineBicFromIban) {
|
||||||
txtRemitteeBankInfo.text = getString(R.string.dialog_transfer_money_could_not_determine_bic_from_iban, enteredIban.substring(4, InputValidator.MinimumLengthToDetermineBicFromIban))
|
txtRecipientBankInfo.text = getString(R.string.dialog_transfer_money_could_not_determine_bic_from_iban, enteredIban.substring(4, InputValidator.MinimumLengthToDetermineBicFromIban))
|
||||||
txtRemitteeBankInfo.visibility = View.VISIBLE
|
txtRecipientBankInfo.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
txtRemitteeBankInfo.visibility = View.GONE
|
txtRecipientBankInfo.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
checkIfRequiredDataEnteredOnUiThread()
|
checkIfRequiredDataEnteredOnUiThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun checkIfRequiredDataEnteredOnUiThread() {
|
protected open fun checkIfRequiredDataEnteredOnUiThread() {
|
||||||
btnTransferMoney.isEnabled = validRemitteeNameEntered && validRemitteeIbanEntered
|
btnTransferMoney.isEnabled = validRecipientNameEntered && validRecipientIbanEntered
|
||||||
&& validRemitteeBicEntered
|
&& validRecipientBicEntered
|
||||||
&& validAmountEntered && validUsageEntered
|
&& validAmountEntered && validReferenceEntered
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun checkIfEnteredRemitteeNameIsValidWhileUserIsTyping() {
|
protected open fun checkIfEnteredRecipientNameIsValidWhileUserIsTyping() {
|
||||||
val enteredRemitteeName = edtxtRemitteeName.text.toString()
|
val enteredRecipientName = edtxtRecipientName.text.toString()
|
||||||
val validationResult = inputValidator.validateRemitteeNameWhileTyping(enteredRemitteeName)
|
val validationResult = inputValidator.validateRecipientNameWhileTyping(enteredRecipientName)
|
||||||
|
|
||||||
this.validRemitteeNameEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
this.validRecipientNameEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
||||||
|
|
||||||
showValidationResult(lytRemitteeName, validationResult)
|
showValidationResult(lytRecipientName, validationResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun checkIfEnteredRemitteeNameIsValidAfterFocusLost() {
|
protected open fun checkIfEnteredRecipientNameIsValidAfterFocusLost() {
|
||||||
val enteredRemitteeName = edtxtRemitteeName.text.toString()
|
val enteredRecipientName = edtxtRecipientName.text.toString()
|
||||||
val validationResult = inputValidator.validateRemitteeName(enteredRemitteeName)
|
val validationResult = inputValidator.validateRecipientName(enteredRecipientName)
|
||||||
|
|
||||||
this.validRemitteeNameEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
this.validRecipientNameEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
||||||
|
|
||||||
if (validationResult.validationSuccessful == false) { // only update hint / error if validation fails, don't hide previous hint / error otherwise
|
if (validationResult.validationSuccessful == false) { // only update hint / error if validation fails, don't hide previous hint / error otherwise
|
||||||
showValidationResult(lytRemitteeName, validationResult)
|
showValidationResult(lytRecipientName, validationResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun checkIfEnteredRemitteeIbanIsValidWhileUserIsTyping() {
|
protected open fun checkIfEnteredRecipientIbanIsValidWhileUserIsTyping() {
|
||||||
val enteredIban = edtxtRemitteeIban.text.toString()
|
val enteredIban = edtxtRecipientIban.text.toString()
|
||||||
val validationResult = inputValidator.validateIbanWhileTyping(enteredIban)
|
val validationResult = inputValidator.validateIbanWhileTyping(enteredIban)
|
||||||
|
|
||||||
this.validRemitteeIbanEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
this.validRecipientIbanEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
||||||
|
|
||||||
showValidationResult(lytRemitteeIban, validationResult)
|
showValidationResult(lytRecipientIban, validationResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun checkIfEnteredRemitteeIbanIsValidAfterFocusLost() {
|
protected open fun checkIfEnteredRecipientIbanIsValidAfterFocusLost() {
|
||||||
val validationResult = inputValidator.validateIban(edtxtRemitteeIban.text.toString())
|
val validationResult = inputValidator.validateIban(edtxtRecipientIban.text.toString())
|
||||||
|
|
||||||
this.validRemitteeIbanEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
this.validRecipientIbanEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
||||||
|
|
||||||
if (validationResult.validationSuccessful == false) { // only update hint / error if validation fails, don't hide previous hint / error otherwise
|
if (validationResult.validationSuccessful == false) { // only update hint / error if validation fails, don't hide previous hint / error otherwise
|
||||||
showValidationResult(lytRemitteeIban, validationResult)
|
showValidationResult(lytRecipientIban, validationResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,12 +437,12 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun checkIfEnteredUsageTextIsValid() {
|
protected open fun checkIfEnteredReferenceTextIsValid() {
|
||||||
val validationResult = inputValidator.validateUsage(edtxtUsage.text.toString())
|
val validationResult = inputValidator.validateReference(edtxtReference.text.toString())
|
||||||
|
|
||||||
this.validUsageEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
this.validReferenceEntered = validationResult.validationSuccessfulOrCouldCorrectString
|
||||||
|
|
||||||
showValidationResult(lytUsage, validationResult)
|
showValidationResult(lytReference, validationResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun showValidationResult(textInputLayout: TextInputLayout, validationResult: ValidationResult) {
|
protected open fun showValidationResult(textInputLayout: TextInputLayout, validationResult: ValidationResult) {
|
||||||
|
@ -475,7 +475,7 @@ open class TransferMoneyDialog : DialogFragment() {
|
||||||
|
|
||||||
(textInputLayout.layoutParams as? ViewGroup.MarginLayoutParams)?.let { params ->
|
(textInputLayout.layoutParams as? ViewGroup.MarginLayoutParams)?.let { params ->
|
||||||
val isShowingHintOrError = validationResult.validationError != null || validationResult.validationHint != null
|
val isShowingHintOrError = validationResult.validationError != null || validationResult.validationHint != null
|
||||||
params.bottomMargin = if (isShowingHintOrError == false || textInputLayout == lytUsage) 0
|
params.bottomMargin = if (isShowingHintOrError == false || textInputLayout == lytReference) 0
|
||||||
else context!!.getDimension(R.dimen.dialog_transfer_money_input_fields_bottom_margin_when_displaying_validation_label)
|
else context!!.getDimension(R.dimen.dialog_transfer_money_input_fields_bottom_margin_when_displaying_validation_label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import net.dankito.banking.ui.model.parameters.TransferMoneyData
|
||||||
import net.dankito.banking.ui.model.responses.GetTransactionsResponse
|
import net.dankito.banking.ui.model.responses.GetTransactionsResponse
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
import net.dankito.utils.android.extensions.asActivity
|
import net.dankito.utils.android.extensions.asActivity
|
||||||
import net.dankito.utils.android.extensions.getDimension
|
|
||||||
import net.dankito.utils.multiplatform.sum
|
import net.dankito.utils.multiplatform.sum
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -148,8 +147,8 @@ class HomeFragment : Fragment() {
|
||||||
|
|
||||||
override fun onContextItemSelected(item: MenuItem): Boolean {
|
override fun onContextItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.mnitmNewTransferToSameRemittee -> {
|
R.id.mnitmNewTransferToSameTransactionParty -> {
|
||||||
newTransferToSameRemittee()
|
newTransferToSameTransactionParty()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.mnitmNewTransferWithSameData -> {
|
R.id.mnitmNewTransferWithSameData -> {
|
||||||
|
@ -211,9 +210,9 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun newTransferToSameRemittee() {
|
private fun newTransferToSameTransactionParty() {
|
||||||
transactionAdapter.selectedTransaction?.let { selectedTransaction ->
|
transactionAdapter.selectedTransaction?.let { selectedTransaction ->
|
||||||
presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransactionWithoutAmountAndUsage(selectedTransaction))
|
presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransactionWithoutAmountAndReference(selectedTransaction))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,14 +47,14 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/lytRemitteeName"
|
android:id="@+id/lytRecipientName"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/dialog_transfer_money_remittee_name"
|
android:hint="@string/dialog_transfer_money_recipient_name"
|
||||||
>
|
>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/edtxtRemitteeName"
|
android:id="@+id/edtxtRecipientName"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/dialog_transfer_money_input_fields_height"
|
android:layout_height="@dimen/dialog_transfer_money_input_fields_height"
|
||||||
android:inputType="textPersonName"
|
android:inputType="textPersonName"
|
||||||
|
@ -67,14 +67,14 @@
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/lytRemitteeIban"
|
android:id="@+id/lytRecipientIban"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/dialog_transfer_money_remittee_iban"
|
android:hint="@string/dialog_transfer_money_recipient_iban"
|
||||||
>
|
>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/edtxtRemitteeIban"
|
android:id="@+id/edtxtRecipientIban"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/dialog_transfer_money_autocomplete_fields_height"
|
android:layout_height="@dimen/dialog_transfer_money_autocomplete_fields_height"
|
||||||
android:inputType="textCapCharacters"
|
android:inputType="textCapCharacters"
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtRemitteeBankInfo"
|
android:id="@+id/txtRecipientBankInfo"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/TextAppearance.AppCompat.Small"
|
style="@style/TextAppearance.AppCompat.Small"
|
||||||
|
@ -109,14 +109,14 @@
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/lytUsage"
|
android:id="@+id/lytReference"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/dialog_transfer_money_usage"
|
android:hint="@string/dialog_transfer_money_reference"
|
||||||
>
|
>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/edtxtUsage"
|
android:id="@+id/edtxtReference"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/dialog_transfer_money_input_fields_height"
|
android:layout_height="@dimen/dialog_transfer_money_input_fields_height"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
|
@ -127,20 +127,20 @@
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:id="@+id/lytInstantPayment"
|
android:id="@+id/lytRealTimeTransfer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="30dp"
|
android:layout_height="30dp"
|
||||||
android:layout_marginTop="@dimen/dialog_transfer_money_instant_payment_margin_top"
|
android:layout_marginTop="@dimen/dialog_transfer_money_real_time_transfer_margin_top"
|
||||||
android:layout_marginBottom="@dimen/dialog_transfer_money_instant_payment_margin_bottom"
|
android:layout_marginBottom="@dimen/dialog_transfer_money_real_time_transfer_margin_bottom"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_marginRight="@dimen/dialog_transfer_money_instant_payment_show_info_button_margin_end"
|
android:layout_marginRight="@dimen/dialog_transfer_money_real_time_transfer_show_info_button_margin_end"
|
||||||
android:layout_marginEnd="@dimen/dialog_transfer_money_instant_payment_show_info_button_margin_end"
|
android:layout_marginEnd="@dimen/dialog_transfer_money_real_time_transfer_show_info_button_margin_end"
|
||||||
>
|
>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatCheckBox
|
<androidx.appcompat.widget.AppCompatCheckBox
|
||||||
android:id="@+id/chkbxInstantPayment"
|
android:id="@+id/chkbxRealTimeTransfer"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
@ -148,18 +148,18 @@
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAlignment="gravity"
|
android:textAlignment="gravity"
|
||||||
android:textSize="@dimen/view_instant_payment_info_text_size"
|
android:textSize="@dimen/view_real_time_transfer_info_text_size"
|
||||||
android:text="@string/dialog_transfer_money_instant_payment"
|
android:text="@string/dialog_transfer_money_real_time_transfer"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/btnShowInstantPaymentInfo"
|
android:id="@+id/btnShowRealTimeTransferInfo"
|
||||||
android:layout_width="@dimen/dialog_transfer_money_instant_payment_show_info_button_size"
|
android:layout_width="@dimen/dialog_transfer_money_real_time_transfer_show_info_button_size"
|
||||||
android:layout_height="@dimen/dialog_transfer_money_instant_payment_show_info_button_size"
|
android:layout_height="@dimen/dialog_transfer_money_real_time_transfer_show_info_button_size"
|
||||||
android:layout_weight="0"
|
android:layout_weight="0"
|
||||||
android:layout_gravity="start|center_vertical"
|
android:layout_gravity="start|center_vertical"
|
||||||
android:layout_marginLeft="@dimen/dialog_transfer_money_instant_payment_show_info_button_margin_start"
|
android:layout_marginLeft="@dimen/dialog_transfer_money_real_time_transfer_show_info_button_margin_start"
|
||||||
android:layout_marginStart="@dimen/dialog_transfer_money_instant_payment_show_info_button_margin_start"
|
android:layout_marginStart="@dimen/dialog_transfer_money_real_time_transfer_show_info_button_margin_start"
|
||||||
android:background="@null"
|
android:background="@null"
|
||||||
app:srcCompat="@drawable/ic_baseline_info_24"
|
app:srcCompat="@drawable/ic_baseline_info_24"
|
||||||
android:tint="@color/infoIconColor"
|
android:tint="@color/infoIconColor"
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
android:id="@+id/txtvwTransactionLabel"
|
android:id="@+id/txtvwTransactionLabel"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="@dimen/list_item_account_transaction_space_between_label_and_usage"
|
android:layout_marginBottom="@dimen/list_item_account_transaction_space_between_label_and_reference"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:textSize="@dimen/list_item_account_transaction_label_text_size"
|
android:textSize="@dimen/list_item_account_transaction_label_text_size"
|
||||||
|
@ -34,14 +34,14 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvwUsage"
|
android:id="@+id/txtvwReference"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAlignment="gravity"
|
android:textAlignment="gravity"
|
||||||
android:lines="2"
|
android:lines="2"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:textSize="@dimen/list_item_account_transaction_usage_text_size"
|
android:textSize="@dimen/list_item_account_transaction_reference_text_size"
|
||||||
android:textColor="@color/textColorSecondary"
|
android:textColor="@color/textColorSecondary"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:padding="@dimen/list_item_remittee_padding"
|
android:padding="@dimen/list_item_recipient_padding"
|
||||||
>
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvwRemitteeName"
|
android:id="@+id/txtvwRecipientName"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/TextAppearance.AppCompat.Medium"
|
style="@style/TextAppearance.AppCompat.Medium"
|
||||||
|
@ -21,10 +21,10 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvwRemitteeBankName"
|
android:id="@+id/txtvwRecipientBankName"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/list_item_remittee_space_between_fields"
|
android:layout_marginTop="@dimen/list_item_recipient_space_between_fields"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
@ -35,11 +35,11 @@
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/list_item_remittee_space_between_fields"
|
android:layout_marginTop="@dimen/list_item_recipient_space_between_fields"
|
||||||
>
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvwRemitteeAccountId"
|
android:id="@+id/txtvwRecipientAccountId"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvwRemitteeBankCode"
|
android:id="@+id/txtvwRecipientBankCode"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
|
@ -18,8 +18,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/TextAppearance.AppCompat.Medium"
|
style="@style/TextAppearance.AppCompat.Medium"
|
||||||
android:textSize="@dimen/view_instant_payment_info_text_size"
|
android:textSize="@dimen/view_real_time_transfer_info_text_size"
|
||||||
android:text="@string/dialog_transfer_money_instant_payment_info"
|
android:text="@string/dialog_transfer_money_real_time_transfer_info"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -27,14 +27,14 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/lytButtonBar"
|
android:id="@+id/lytButtonBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/view_instant_payment_info_dismiss_button_height"
|
android:layout_height="@dimen/view_real_time_info_dismiss_button_height"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
>
|
>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnDismissPopup"
|
android:id="@+id/btnDismissPopup"
|
||||||
android:layout_width="@dimen/view_instant_payment_info_dismiss_button_width"
|
android:layout_width="@dimen/view_real_time_transfer_info_dismiss_button_width"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
android:text="@android:string/ok"
|
android:text="@android:string/ok"
|
|
@ -2,7 +2,7 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/mnitmNewTransferToSameRemittee"
|
android:id="@+id/mnitmNewTransferToSameTransactionParty"
|
||||||
android:title="@string/fragment_home_transfer_money_to"
|
android:title="@string/fragment_home_transfer_money_to"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -53,14 +53,14 @@
|
||||||
<string name="dialog_add_account_message_could_not_add_account">Konto konnte nicht hinzugefügt werden.\n\nFehlermeldung Ihrer Bank:\n\n%s</string>
|
<string name="dialog_add_account_message_could_not_add_account">Konto konnte nicht hinzugefügt werden.\n\nFehlermeldung Ihrer Bank:\n\n%s</string>
|
||||||
|
|
||||||
<string name="dialog_transfer_money_account">Konto:</string>
|
<string name="dialog_transfer_money_account">Konto:</string>
|
||||||
<string name="dialog_transfer_money_remittee_name">Name:</string>
|
<string name="dialog_transfer_money_recipient_name">Name:</string>
|
||||||
<string name="dialog_transfer_money_remittee_iban">IBAN:</string>
|
<string name="dialog_transfer_money_recipient_iban">IBAN:</string>
|
||||||
<string name="dialog_transfer_money_bic_detected_from_iban">BIC: %1$s, %2$s</string>
|
<string name="dialog_transfer_money_bic_detected_from_iban">BIC: %1$s, %2$s</string>
|
||||||
<string name="dialog_transfer_money_could_not_determine_bic_from_iban">Keine BIC gefunden für BLZ %1$s</string>
|
<string name="dialog_transfer_money_could_not_determine_bic_from_iban">Keine BIC gefunden für BLZ %1$s</string>
|
||||||
<string name="dialog_transfer_money_amount">Betrag:</string>
|
<string name="dialog_transfer_money_amount">Betrag:</string>
|
||||||
<string name="dialog_transfer_money_usage">Verwendungszweck:</string>
|
<string name="dialog_transfer_money_reference">Verwendungszweck:</string>
|
||||||
<string name="dialog_transfer_money_instant_payment">Echtzeitüberweisung (evtl. kostenpflichtig)</string>
|
<string name="dialog_transfer_money_real_time_transfer">Echtzeitüberweisung (evtl. kostenpflichtig)</string>
|
||||||
<string name="dialog_transfer_money_instant_payment_info">Normale Überweisungen werden in der Regel innerhalb eines Werktages gutgeschrieben. Dies gilt jedoch nur zu Geschäftszeiten der Banken, also schon mal nicht am Wochenende und an Feiertagen. Zudem unterscheiden sich die Geschäftszeiten von Bank zu Bank. Meistens gehen diese von 10 - 18 Uhr, manchmal auch bis 22 Uhr, manchmal (Freitags) aber auch nur bis 14 Uhr.
|
<string name="dialog_transfer_money_real_time_transfer_info">Normale Überweisungen werden in der Regel innerhalb eines Werktages gutgeschrieben. Dies gilt jedoch nur zu Geschäftszeiten der Banken, also schon mal nicht am Wochenende und an Feiertagen. Zudem unterscheiden sich die Geschäftszeiten von Bank zu Bank. Meistens gehen diese von 10 - 18 Uhr, manchmal auch bis 22 Uhr, manchmal (Freitags) aber auch nur bis 14 Uhr.
|
||||||
\n\nEchtzeitüberweisungen werden hingegen innerhalb von maximal 10 Sekunden überwiesen, egal an welchem Tag und zu welcher Uhrzeit.
|
\n\nEchtzeitüberweisungen werden hingegen innerhalb von maximal 10 Sekunden überwiesen, egal an welchem Tag und zu welcher Uhrzeit.
|
||||||
\n\nHäufig sind Echtzeitüberweisungen jedoch kostenpflichtig.
|
\n\nHäufig sind Echtzeitüberweisungen jedoch kostenpflichtig.
|
||||||
\n\nOb eine Bank Gebühren für Echtzeitüberweisungen erhebt, kann Bankmeister leider nicht wissen. Dies entnehmen Sie bitte dem Preis- / Leistungsverzeichnis Ihrer Bank.</string>
|
\n\nOb eine Bank Gebühren für Echtzeitüberweisungen erhebt, kann Bankmeister leider nicht wissen. Dies entnehmen Sie bitte dem Preis- / Leistungsverzeichnis Ihrer Bank.</string>
|
||||||
|
@ -120,7 +120,7 @@
|
||||||
<string name="error_invalid_bic_pattern_entered">Eine BIC besteht aus 8 oder 11 Zeichen und folgt dem Muster: ABCDED12(XYZ)</string>
|
<string name="error_invalid_bic_pattern_entered">Eine BIC besteht aus 8 oder 11 Zeichen und folgt dem Muster: ABCDED12(XYZ)</string>
|
||||||
<string name="error_no_amount_entered">Bitte geben Sie den zu überweisenden Betrag ein</string>
|
<string name="error_no_amount_entered">Bitte geben Sie den zu überweisenden Betrag ein</string>
|
||||||
<string name="error_invalid_amount_entered">Bitte geben Sie einen Betrag größer 0 ein.</string>
|
<string name="error_invalid_amount_entered">Bitte geben Sie einen Betrag größer 0 ein.</string>
|
||||||
<string name="error_entered_usage_too_long">Verwendungszweck darf nur 140 Zeichen lang sein</string>
|
<string name="error_entered_recipient_too_long">Verwendungszweck darf nur 140 Zeichen lang sein</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="dialog_send_message_log_message_log_label">Message Log</string>
|
<string name="dialog_send_message_log_message_log_label">Message Log</string>
|
||||||
|
|
|
@ -34,9 +34,9 @@
|
||||||
|
|
||||||
<dimen name="list_item_account_transaction_height">74dp</dimen>
|
<dimen name="list_item_account_transaction_height">74dp</dimen>
|
||||||
<dimen name="list_item_account_transaction_padding">0dp</dimen>
|
<dimen name="list_item_account_transaction_padding">0dp</dimen>
|
||||||
<dimen name="list_item_account_transaction_space_between_label_and_usage">2dp</dimen>
|
<dimen name="list_item_account_transaction_space_between_label_and_reference">2dp</dimen>
|
||||||
<dimen name="list_item_account_transaction_label_text_size">16sp</dimen>
|
<dimen name="list_item_account_transaction_label_text_size">16sp</dimen>
|
||||||
<dimen name="list_item_account_transaction_usage_text_size">14sp</dimen>
|
<dimen name="list_item_account_transaction_reference_text_size">14sp</dimen>
|
||||||
<dimen name="list_item_account_transaction_bank_icon_width_and_height">16dp</dimen>
|
<dimen name="list_item_account_transaction_bank_icon_width_and_height">16dp</dimen>
|
||||||
<dimen name="list_item_account_transaction_bank_icon_margin_top">0dp</dimen>
|
<dimen name="list_item_account_transaction_bank_icon_margin_top">0dp</dimen>
|
||||||
<dimen name="list_item_account_transaction_bank_icon_margin_bottom">2dp</dimen>
|
<dimen name="list_item_account_transaction_bank_icon_margin_bottom">2dp</dimen>
|
||||||
|
@ -75,25 +75,25 @@
|
||||||
<dimen name="dialog_transfer_money_autocomplete_fields_height">50dp</dimen>
|
<dimen name="dialog_transfer_money_autocomplete_fields_height">50dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_input_fields_height">40dp</dimen>
|
<dimen name="dialog_transfer_money_input_fields_height">40dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_input_fields_bottom_margin_when_displaying_validation_label">8dp</dimen>
|
<dimen name="dialog_transfer_money_input_fields_bottom_margin_when_displaying_validation_label">8dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_instant_payment_text_size">14sp</dimen>
|
<dimen name="dialog_transfer_money_real_time_transfer_text_size">14sp</dimen>
|
||||||
<dimen name="dialog_transfer_money_instant_payment_margin_top">6dp</dimen>
|
<dimen name="dialog_transfer_money_real_time_transfer_margin_top">6dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_instant_payment_margin_bottom">6dp</dimen>
|
<dimen name="dialog_transfer_money_real_time_transfer_margin_bottom">6dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_instant_payment_show_info_button_size">20dp</dimen>
|
<dimen name="dialog_transfer_money_real_time_transfer_show_info_button_size">20dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_instant_payment_show_info_button_margin_start">6dp</dimen>
|
<dimen name="dialog_transfer_money_real_time_transfer_show_info_button_margin_start">6dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_instant_payment_show_info_button_margin_end">12dp</dimen>
|
<dimen name="dialog_transfer_money_real_time_transfer_show_info_button_margin_end">12dp</dimen>
|
||||||
<dimen name="dialog_transfer_money_buttons_width">120dp</dimen>
|
<dimen name="dialog_transfer_money_buttons_width">120dp</dimen>
|
||||||
|
|
||||||
<dimen name="list_item_bank_account_padding">2dp</dimen>
|
<dimen name="list_item_bank_account_padding">2dp</dimen>
|
||||||
<dimen name="list_item_bank_account_icon_size">20dp</dimen>
|
<dimen name="list_item_bank_account_icon_size">20dp</dimen>
|
||||||
<dimen name="list_item_bank_account_icon_margin_right">8dp</dimen>
|
<dimen name="list_item_bank_account_icon_margin_right">8dp</dimen>
|
||||||
|
|
||||||
<dimen name="list_item_remittee_padding">4dp</dimen>
|
<dimen name="list_item_recipient_padding">4dp</dimen>
|
||||||
<dimen name="list_item_remittee_space_between_fields">4dp</dimen>
|
<dimen name="list_item_recipient_space_between_fields">4dp</dimen>
|
||||||
|
|
||||||
<dimen name="view_instant_payment_info_padding">8dp</dimen>
|
<dimen name="view_real_time_transfer_info_padding">8dp</dimen>
|
||||||
<dimen name="view_instant_payment_info_text_size">15sp</dimen>
|
<dimen name="view_real_time_transfer_info_text_size">15sp</dimen>
|
||||||
<dimen name="view_instant_payment_info_dismiss_button_width">150dp</dimen>
|
<dimen name="view_real_time_transfer_info_dismiss_button_width">150dp</dimen>
|
||||||
<dimen name="view_instant_payment_info_dismiss_button_height">40dp</dimen>
|
<dimen name="view_real_time_info_dismiss_button_height">40dp</dimen>
|
||||||
|
|
||||||
<dimen name="view_tan_image_controls_buttons_height">40dp</dimen>
|
<dimen name="view_tan_image_controls_buttons_height">40dp</dimen>
|
||||||
<dimen name="view_tan_image_controls_buttons_width">40dp</dimen>
|
<dimen name="view_tan_image_controls_buttons_width">40dp</dimen>
|
||||||
|
|
|
@ -53,17 +53,17 @@
|
||||||
<string name="dialog_add_account_message_could_not_add_account">Could not add account.\n\nError message from your bank:\n\n%s</string>
|
<string name="dialog_add_account_message_could_not_add_account">Could not add account.\n\nError message from your bank:\n\n%s</string>
|
||||||
|
|
||||||
<string name="dialog_transfer_money_account">Account:</string>
|
<string name="dialog_transfer_money_account">Account:</string>
|
||||||
<string name="dialog_transfer_money_remittee_name">Name:</string>
|
<string name="dialog_transfer_money_recipient_name">Name:</string>
|
||||||
<string name="dialog_transfer_money_remittee_iban">IBAN:</string>
|
<string name="dialog_transfer_money_recipient_iban">IBAN:</string>
|
||||||
<string name="dialog_transfer_money_bic_detected_from_iban">BIC: %1$s, %2$s</string>
|
<string name="dialog_transfer_money_bic_detected_from_iban">BIC: %1$s, %2$s</string>
|
||||||
<string name="dialog_transfer_money_could_not_determine_bic_from_iban">No BIC found for bank code %1$s</string>
|
<string name="dialog_transfer_money_could_not_determine_bic_from_iban">No BIC found for bank code %1$s</string>
|
||||||
<string name="dialog_transfer_money_amount">Amount:</string>
|
<string name="dialog_transfer_money_amount">Amount:</string>
|
||||||
<string name="dialog_transfer_money_usage">Usage:</string>
|
<string name="dialog_transfer_money_reference">Reference:</string>
|
||||||
<string name="dialog_transfer_money_instant_payment">Instant payment (may with costs)</string>
|
<string name="dialog_transfer_money_real_time_transfer">Real-time transfer (may with costs)</string>
|
||||||
<string name="dialog_transfer_money_instant_payment_info">Bank transfers are usually credited within one business day. However, this only applies during bank business hours, and therefore not at weekends and on public holidays. In addition, business hours vary from bank to bank. Mostly they are from 10 - 18 o\'clock, sometimes also until 22 o\'clock, but sometimes (e. g. Fridays) only until 14 o\'clock.
|
<string name="dialog_transfer_money_real_time_transfer_info">Bank transfers are usually credited within one business day. However, this only applies during bank business hours, and therefore not at weekends and on public holidays. In addition, business hours vary from bank to bank. Mostly they are from 10 - 18 o\'clock, sometimes also until 22 o\'clock, but sometimes (e. g. Fridays) only until 14 o\'clock.
|
||||||
\n\nInstant payment transfers on the other hand are transferred within a maximum of 10 seconds, regardless of the day and time of day.
|
\n\nReal-time transfers on the other hand are transferred within a maximum of 10 seconds, regardless of the day and time of day.
|
||||||
\n\nHowever, real-time transfers are often subject to a fee.
|
\n\nHowever, real-time transfers are often subject to a fee.
|
||||||
\n\nUnfortunately, Bankmeister cannot know whether a bank charges for instant payment transfers. Please refer to the list of prices and services of your bank.</string>
|
\n\nUnfortunately, Bankmeister cannot know whether a bank charges for real-time transfers. Please refer to the list of prices and services of your bank.</string>
|
||||||
<string name="dialog_transfer_money_transfer">Transfer</string>
|
<string name="dialog_transfer_money_transfer">Transfer</string>
|
||||||
<string name="dialog_transfer_money_message_transfer_successful">Successfully transferred %1$s %2$s to %3$s.</string>
|
<string name="dialog_transfer_money_message_transfer_successful">Successfully transferred %1$s %2$s to %3$s.</string>
|
||||||
<string name="dialog_transfer_money_message_transfer_failed">Could not transfer %1$s %2$s to %3$s.\n\nError message from your bank:\n\n%4$s</string>
|
<string name="dialog_transfer_money_message_transfer_failed">Could not transfer %1$s %2$s to %3$s.\n\nError message from your bank:\n\n%4$s</string>
|
||||||
|
@ -110,17 +110,17 @@
|
||||||
\n\nThey can only be restored, if then still possible, by retrieving it again from your bank server.</string>
|
\n\nThey can only be restored, if then still possible, by retrieving it again from your bank server.</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="error_no_name_entered">Please enter remittee\'s name</string>
|
<string name="error_no_name_entered">Please enter recipient\'s name</string>
|
||||||
<string name="error_entered_name_too_long">Name may only have 70 characters</string>
|
<string name="error_entered_name_too_long">Name may only have 70 characters</string>
|
||||||
<string name="error_invalid_sepa_characters_entered">Invalid character(s) entered: %s</string>
|
<string name="error_invalid_sepa_characters_entered">Invalid character(s) entered: %s</string>
|
||||||
<string name="error_no_iban_entered">Please enter remittee\'s IBAN</string>
|
<string name="error_no_iban_entered">Please enter recipient\'s IBAN</string>
|
||||||
<string name="error_invalid_iban_characters_entered">Invalid character(s) entered: %s</string>
|
<string name="error_invalid_iban_characters_entered">Invalid character(s) entered: %s</string>
|
||||||
<string name="error_invalid_iban_pattern_entered">IBAN has to have pattern: EN12 1234 5678 9012 3456 78</string>
|
<string name="error_invalid_iban_pattern_entered">IBAN has to have pattern: EN12 1234 5678 9012 3456 78</string>
|
||||||
<string name="error_invalid_bic_characters_entered">Invalid character(s) entered: %s</string>
|
<string name="error_invalid_bic_characters_entered">Invalid character(s) entered: %s</string>
|
||||||
<string name="error_invalid_bic_pattern_entered">A BIC consists of 8 or 11 characters and has the pattern: ABCDED12(XYZ)</string>
|
<string name="error_invalid_bic_pattern_entered">A BIC consists of 8 or 11 characters and has the pattern: ABCDED12(XYZ)</string>
|
||||||
<string name="error_no_amount_entered">Please enter the amount to be transferred</string>
|
<string name="error_no_amount_entered">Please enter the amount to be transferred</string>
|
||||||
<string name="error_invalid_amount_entered">Please enter an amount greater zero.</string>
|
<string name="error_invalid_amount_entered">Please enter an amount greater zero.</string>
|
||||||
<string name="error_entered_usage_too_long">Usage may only have 140 characters</string>
|
<string name="error_entered_recipient_too_long">Reference may only have 140 characters</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="dialog_send_message_log_message_log_label">Message log</string>
|
<string name="dialog_send_message_log_message_log_label">Message log</string>
|
||||||
|
|
|
@ -12,7 +12,7 @@ import net.dankito.banking.util.BankIconFinder
|
||||||
import net.dankito.banking.bankfinder.LuceneBankFinder
|
import net.dankito.banking.bankfinder.LuceneBankFinder
|
||||||
import net.dankito.banking.persistence.LuceneBankingPersistence
|
import net.dankito.banking.persistence.LuceneBankingPersistence
|
||||||
import net.dankito.banking.persistence.mapper.EntitiesModelCreator
|
import net.dankito.banking.persistence.mapper.EntitiesModelCreator
|
||||||
import net.dankito.banking.search.LuceneRemitteeSearcher
|
import net.dankito.banking.search.LuceneTransactionPartySearcher
|
||||||
import net.dankito.banking.util.JacksonJsonSerializer
|
import net.dankito.banking.util.JacksonJsonSerializer
|
||||||
import net.dankito.banking.util.extraction.JavaTextExtractorRegistry
|
import net.dankito.banking.util.extraction.JavaTextExtractorRegistry
|
||||||
import net.dankito.text.extraction.TextExtractorRegistry
|
import net.dankito.text.extraction.TextExtractorRegistry
|
||||||
|
@ -47,9 +47,9 @@ class MainWindow : View(messages["application.title"]) {
|
||||||
|
|
||||||
private val presenter = BankingPresenter(fints4kBankingClientCreator(modelCreator, serializer),
|
private val presenter = BankingPresenter(fints4kBankingClientCreator(modelCreator, serializer),
|
||||||
LuceneBankFinder(indexFolder), dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder),
|
LuceneBankFinder(indexFolder), dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder),
|
||||||
RouterJavaFx(), modelCreator, LuceneRemitteeSearcher(indexFolder), BankIconFinder(), textExtractorRegistry)
|
RouterJavaFx(), modelCreator, LuceneTransactionPartySearcher(indexFolder), BankIconFinder(), textExtractorRegistry)
|
||||||
// private val presenter = BankingPresenter(hbci4jBankingClientCreator(), LuceneBankFinder(indexFolder),
|
// private val presenter = BankingPresenter(hbci4jBankingClientCreator(), LuceneBankFinder(indexFolder),
|
||||||
// dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder), RouterJavaFx(), modelCreator, LuceneRemitteeSearcher(indexFolder),
|
// dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder), RouterJavaFx(), modelCreator, LuceneTransactionPartySearcher(indexFolder),
|
||||||
// BankIconFinder(), textExtractorRegistry)
|
// BankIconFinder(), textExtractorRegistry)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,9 @@ account.transactions.control.view.balance.label=Balance:
|
||||||
account.transactions.control.view.could.not.retrieve.account.transactions=Could not retrieve account transactions for \'%1$s\'.\n\nError message from your bank:\n\n%2$s
|
account.transactions.control.view.could.not.retrieve.account.transactions=Could not retrieve account transactions for \'%1$s\'.\n\nError message from your bank:\n\n%2$s
|
||||||
|
|
||||||
account.transactions.table.column.header.value.date=Value date
|
account.transactions.table.column.header.value.date=Value date
|
||||||
account.transactions.table.column.header.usage=Usage
|
account.transactions.table.column.header.reference=Reference
|
||||||
account.transactions.table.column.header.amount=Amount
|
account.transactions.table.column.header.amount=Amount
|
||||||
account.transactions.table.context.menu.new.transfer.to.same.remittee=Transfer money to %s
|
account.transactions.table.context.menu.new.transfer.to.same.recipient=Transfer money to %s
|
||||||
account.transactions.table.context.menu.new.transfer.with.same.data=New transfer with same data
|
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
|
account.transactions.table.context.menu.show.transaction.details=Show details
|
||||||
|
|
||||||
|
@ -62,13 +62,13 @@ enter.tan.dialog.tan.error.changing.tan.medium=Could not change TAN medium to \'
|
||||||
|
|
||||||
transfer.money.dialog.title=Transfer money
|
transfer.money.dialog.title=Transfer money
|
||||||
transfer.money.dialog.account.label=Account:
|
transfer.money.dialog.account.label=Account:
|
||||||
transfer.money.dialog.remittee.name.label=Remittee:
|
transfer.money.dialog.recipient.name.label=Recipient:
|
||||||
transfer.money.dialog.remittee.iban.label=IBAN:
|
transfer.money.dialog.recipient.iban.label=IBAN:
|
||||||
transfer.money.dialog.remittee.bank.label=Bank:
|
transfer.money.dialog.recipient.bank.label=Bank:
|
||||||
transfer.money.dialog.remittee.bic.label=BIC:
|
transfer.money.dialog.recipient.bic.label=BIC:
|
||||||
transfer.money.dialog.amount.label=Amount:
|
transfer.money.dialog.amount.label=Amount:
|
||||||
transfer.money.dialog.usage.label=Usage:
|
transfer.money.dialog.reference.label=Reference:
|
||||||
transfer.money.dialog.instant.payment.label=Instant payment
|
transfer.money.dialog.real.time.transfer.label=Real-time transfer
|
||||||
transfer.money.dialog.transfer.money.label=Transfer
|
transfer.money.dialog.transfer.money.label=Transfer
|
||||||
transfer.money.dialog.bank.name.will.be.entered.automatically=Will be entered automatically
|
transfer.money.dialog.bank.name.will.be.entered.automatically=Will be entered automatically
|
||||||
transfer.money.dialog.bank.not.found.for.iban=No bank found for this IBAN
|
transfer.money.dialog.bank.not.found.for.iban=No bank found for this IBAN
|
||||||
|
|
|
@ -28,9 +28,9 @@ account.transactions.control.view.balance.label=Saldo:
|
||||||
account.transactions.control.view.could.not.retrieve.account.transactions=Kontoumsätze für \'%1$s\' konnten nicht empfangen werden.\n\nFehlermeldung Ihrer Bank:\n\n%2$s
|
account.transactions.control.view.could.not.retrieve.account.transactions=Kontoumsätze für \'%1$s\' konnten nicht empfangen werden.\n\nFehlermeldung Ihrer Bank:\n\n%2$s
|
||||||
|
|
||||||
account.transactions.table.column.header.value.date=Buchungstag
|
account.transactions.table.column.header.value.date=Buchungstag
|
||||||
account.transactions.table.column.header.usage=Verwendungszweck
|
account.transactions.table.column.header.reference=Verwendungszweck
|
||||||
account.transactions.table.column.header.amount=Betrag
|
account.transactions.table.column.header.amount=Betrag
|
||||||
account.transactions.table.context.menu.new.transfer.to.same.remittee=Neue Überweisung an %s
|
account.transactions.table.context.menu.new.transfer.to.same.recipient=Neue Überweisung an %s
|
||||||
account.transactions.table.context.menu.new.transfer.with.same.data=Neue Überweisung mit gleichen Daten
|
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
|
account.transactions.table.context.menu.show.transaction.details=Details anzeigen
|
||||||
|
|
||||||
|
@ -62,13 +62,13 @@ enter.tan.dialog.tan.error.changing.tan.medium=TAN Medium konnte nicht geändert
|
||||||
|
|
||||||
transfer.money.dialog.title=Neue Überweisung
|
transfer.money.dialog.title=Neue Überweisung
|
||||||
transfer.money.dialog.account.label=Konto:
|
transfer.money.dialog.account.label=Konto:
|
||||||
transfer.money.dialog.remittee.name.label=Begünstigter (Name oder Firma):
|
transfer.money.dialog.recipient.name.label=Begünstigter (Name oder Firma):
|
||||||
transfer.money.dialog.remittee.iban.label=IBAN:
|
transfer.money.dialog.recipient.iban.label=IBAN:
|
||||||
transfer.money.dialog.remittee.bank.label=Bank:
|
transfer.money.dialog.recipient.bank.label=Bank:
|
||||||
transfer.money.dialog.remittee.bic.label=BIC:
|
transfer.money.dialog.recipient.bic.label=BIC:
|
||||||
transfer.money.dialog.amount.label=Betrag:
|
transfer.money.dialog.amount.label=Betrag:
|
||||||
transfer.money.dialog.usage.label=Verwendungszweck:
|
transfer.money.dialog.reference.label=Verwendungszweck:
|
||||||
transfer.money.dialog.instant.payment.label=Echtzeitüberweisung
|
transfer.money.dialog.real.time.transfer.label=Echtzeitüberweisung
|
||||||
transfer.money.dialog.transfer.money.label=Überweisen
|
transfer.money.dialog.transfer.money.label=Überweisen
|
||||||
transfer.money.dialog.bank.name.will.be.entered.automatically=Wird automatisch eingetragen
|
transfer.money.dialog.bank.name.will.be.entered.automatically=Wird automatisch eingetragen
|
||||||
transfer.money.dialog.bank.not.found.for.iban=Für diese IBAN wurde keine Bank gefunden
|
transfer.money.dialog.bank.not.found.for.iban=Für diese IBAN wurde keine Bank gefunden
|
||||||
|
|
|
@ -48,7 +48,7 @@ open class AccountTransactionsTable @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
columns.add(TableColumn<IAccountTransaction, IAccountTransaction>(messages["account.transactions.table.column.header.usage"]).apply {
|
columns.add(TableColumn<IAccountTransaction, IAccountTransaction>(messages["account.transactions.table.column.header.reference"]).apply {
|
||||||
|
|
||||||
this.cellFormat {
|
this.cellFormat {
|
||||||
contentDisplay = ContentDisplay.GRAPHIC_ONLY
|
contentDisplay = ContentDisplay.GRAPHIC_ONLY
|
||||||
|
@ -72,7 +72,7 @@ open class AccountTransactionsTable @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label(it.usage) {
|
label(it.reference) {
|
||||||
vboxConstraints {
|
vboxConstraints {
|
||||||
margin = LabelMargin
|
margin = LabelMargin
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,8 @@ open class AccountTransactionsView(private val presenter: BankingPresenter) : Vi
|
||||||
|
|
||||||
contextMenu.apply {
|
contextMenu.apply {
|
||||||
if (selectedItem.canCreateMoneyTransferFrom) {
|
if (selectedItem.canCreateMoneyTransferFrom) {
|
||||||
item(String.format(FX.messages["account.transactions.table.context.menu.new.transfer.to.same.remittee"], selectedItem.otherPartyName)) {
|
item(String.format(FX.messages["account.transactions.table.context.menu.new.transfer.to.same.recipient"], selectedItem.otherPartyName)) {
|
||||||
action { newTransferToSameRemittee(selectedItem) }
|
action { newTransferToSameTransactionParty(selectedItem) }
|
||||||
}
|
}
|
||||||
|
|
||||||
item(String.format(FX.messages["account.transactions.table.context.menu.new.transfer.with.same.data"], selectedItem.otherPartyName)) {
|
item(String.format(FX.messages["account.transactions.table.context.menu.new.transfer.with.same.data"], selectedItem.otherPartyName)) {
|
||||||
|
@ -110,8 +110,8 @@ open class AccountTransactionsView(private val presenter: BankingPresenter) : Vi
|
||||||
// presenter.showTransactionDetailsWindow(transaction.item)
|
// presenter.showTransactionDetailsWindow(transaction.item)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun newTransferToSameRemittee(transaction: IAccountTransaction) {
|
protected open fun newTransferToSameTransactionParty(transaction: IAccountTransaction) {
|
||||||
presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransactionWithoutAmountAndUsage(transaction))
|
presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransactionWithoutAmountAndReference(transaction))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun newTransferWithSameData(transaction: IAccountTransaction) {
|
protected open fun newTransferWithSameData(transaction: IAccountTransaction) {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package net.dankito.banking.ui.javafx.dialogs.cashtransfer
|
||||||
|
|
||||||
|
import net.dankito.banking.search.TransactionParty
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
|
||||||
|
open class RecipientListCellFragment : ListCellFragment<TransactionParty>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ItemHeight = 60.0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open val recipient = RecipientViewModel().bindTo(this)
|
||||||
|
|
||||||
|
|
||||||
|
override val root = vbox {
|
||||||
|
label(recipient.name)
|
||||||
|
|
||||||
|
label(recipient.bankName) {
|
||||||
|
vboxConstraints {
|
||||||
|
marginTopBottom(6.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label(recipient.iban)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package net.dankito.banking.ui.javafx.dialogs.cashtransfer
|
package net.dankito.banking.ui.javafx.dialogs.cashtransfer
|
||||||
|
|
||||||
import javafx.beans.property.SimpleStringProperty
|
import javafx.beans.property.SimpleStringProperty
|
||||||
import net.dankito.banking.search.Remittee
|
import net.dankito.banking.search.TransactionParty
|
||||||
import tornadofx.ItemViewModel
|
import tornadofx.ItemViewModel
|
||||||
|
|
||||||
|
|
||||||
open class RemitteeViewModel : ItemViewModel<Remittee>() {
|
open class RecipientViewModel : ItemViewModel<TransactionParty>() {
|
||||||
|
|
||||||
val name = bind { SimpleStringProperty(item?.name) }
|
val name = bind { SimpleStringProperty(item?.name) }
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package net.dankito.banking.ui.javafx.dialogs.cashtransfer
|
|
||||||
|
|
||||||
import net.dankito.banking.search.Remittee
|
|
||||||
import tornadofx.*
|
|
||||||
|
|
||||||
|
|
||||||
open class RemitteeListCellFragment : ListCellFragment<Remittee>() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val ItemHeight = 60.0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
open val remittee = RemitteeViewModel().bindTo(this)
|
|
||||||
|
|
||||||
|
|
||||||
override val root = vbox {
|
|
||||||
label(remittee.name)
|
|
||||||
|
|
||||||
label(remittee.bankName) {
|
|
||||||
vboxConstraints {
|
|
||||||
marginTopBottom(6.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label(remittee.iban)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,7 +18,7 @@ import net.dankito.banking.ui.model.responses.BankingClientResponse
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
import net.dankito.banking.util.InputValidator
|
import net.dankito.banking.util.InputValidator
|
||||||
import net.dankito.banking.bankfinder.BankInfo
|
import net.dankito.banking.bankfinder.BankInfo
|
||||||
import net.dankito.banking.search.Remittee
|
import net.dankito.banking.search.TransactionParty
|
||||||
import net.dankito.utils.multiplatform.toBigDecimal
|
import net.dankito.utils.multiplatform.toBigDecimal
|
||||||
import net.dankito.banking.ui.javafx.extensions.focusNextControl
|
import net.dankito.banking.ui.javafx.extensions.focusNextControl
|
||||||
import net.dankito.utils.javafx.ui.controls.AutoCompletionSearchTextField
|
import net.dankito.utils.javafx.ui.controls.AutoCompletionSearchTextField
|
||||||
|
@ -53,30 +53,31 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
|
|
||||||
protected val showBankAccounts = SimpleBooleanProperty(bankAccountsSupportingTransferringMoney.size > 1)
|
protected val showBankAccounts = SimpleBooleanProperty(bankAccountsSupportingTransferringMoney.size > 1)
|
||||||
|
|
||||||
protected val remitteeName = SimpleStringProperty(preselectedValues?.creditorName ?: "")
|
protected val recipientName = SimpleStringProperty(preselectedValues?.recipientName ?: "")
|
||||||
|
|
||||||
protected val remitteeIban = SimpleStringProperty(preselectedValues?.creditorIban ?: "")
|
protected val recipientIban = SimpleStringProperty(preselectedValues?.recipientAccountId ?: "")
|
||||||
|
|
||||||
protected val remitteeBank = SimpleObjectProperty<BankInfo>()
|
protected val recipientBank = SimpleObjectProperty<BankInfo>()
|
||||||
|
|
||||||
protected val remitteeBankName = SimpleStringProperty()
|
protected val recipientBankName = SimpleStringProperty()
|
||||||
|
|
||||||
protected val remitteeBic = SimpleStringProperty(preselectedValues?.creditorBic ?: "")
|
protected val recipientBic = SimpleStringProperty(preselectedValues?.recipientBankCode ?: "")
|
||||||
|
|
||||||
protected val amount = SimpleDoubleProperty(preselectedValues?.amount?.toDouble() ?: 0.0)
|
protected val amount = SimpleDoubleProperty(preselectedValues?.amount?.toDouble() ?: 0.0)
|
||||||
|
|
||||||
protected val usage = SimpleStringProperty(preselectedValues?.usage ?: "")
|
protected val reference = SimpleStringProperty(preselectedValues?.reference ?: "")
|
||||||
|
|
||||||
protected val instantPayment = SimpleBooleanProperty(false)
|
protected val realTimeTransfer = SimpleBooleanProperty(false)
|
||||||
|
|
||||||
protected val supportsInstantPayment = SimpleBooleanProperty(selectedBankAccount.value?.supportsInstantPaymentMoneyTransfer ?: false)
|
protected val supportsRealTimeTransfer
|
||||||
|
= SimpleBooleanProperty(selectedBankAccount.value?.supportsRealTimeTransfer ?: false)
|
||||||
|
|
||||||
protected val requiredDataEntered = SimpleBooleanProperty(false)
|
protected val requiredDataEntered = SimpleBooleanProperty(false)
|
||||||
|
|
||||||
|
|
||||||
protected var txtfldRemitteeName: AutoCompletionSearchTextField<Remittee> by singleAssign()
|
protected var txtfldRecipientName: AutoCompletionSearchTextField<TransactionParty> by singleAssign()
|
||||||
|
|
||||||
protected var lastSearchRemitteeJob: Job? = null
|
protected var lastSearchRecipientJob: Job? = null
|
||||||
|
|
||||||
|
|
||||||
protected val inputValidator = InputValidator()
|
protected val inputValidator = InputValidator()
|
||||||
|
@ -87,11 +88,11 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
init {
|
init {
|
||||||
selectedBankAccount.addListener { _, _, newValue -> selectedBankAccountChanged(newValue) }
|
selectedBankAccount.addListener { _, _, newValue -> selectedBankAccountChanged(newValue) }
|
||||||
|
|
||||||
remitteeName.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
recipientName.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
||||||
remitteeIban.addListener { _, _, newValue -> tryToGetBicFromIban(newValue) }
|
recipientIban.addListener { _, _, newValue -> tryToGetBicFromIban(newValue) }
|
||||||
remitteeBic.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
recipientBic.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
||||||
amount.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
amount.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
||||||
usage.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
reference.addListener { _, _, _ -> checkIfRequiredDataEnteredOnUiThread() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,30 +132,30 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field(messages["transfer.money.dialog.remittee.name.label"]) {
|
field(messages["transfer.money.dialog.recipient.name.label"]) {
|
||||||
fixedHeight = FieldHeight
|
fixedHeight = FieldHeight
|
||||||
|
|
||||||
txtfldRemitteeName = autocompletionsearchtextfield(this@TransferMoneyDialog.remitteeName) {
|
txtfldRecipientName = autocompletionsearchtextfield(this@TransferMoneyDialog.recipientName) {
|
||||||
fixedHeight = TextFieldHeight
|
fixedHeight = TextFieldHeight
|
||||||
|
|
||||||
textProperty().addListener { _, _, newValue -> searchRemittees(newValue) }
|
textProperty().addListener { _, _, newValue -> searchRecipients(newValue) }
|
||||||
|
|
||||||
onAutoCompletion = { remitteeSelected(it) }
|
onAutoCompletion = { recipientSelected(it) }
|
||||||
listCellFragment = RemitteeListCellFragment::class
|
listCellFragment = RecipientListCellFragment::class
|
||||||
|
|
||||||
setPrefItemHeight(RemitteeListCellFragment.ItemHeight)
|
setPrefItemHeight(RecipientListCellFragment.ItemHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field(messages["transfer.money.dialog.remittee.iban.label"]) {
|
field(messages["transfer.money.dialog.recipient.iban.label"]) {
|
||||||
fixedHeight = FieldHeight
|
fixedHeight = FieldHeight
|
||||||
|
|
||||||
textfield(remitteeIban) {
|
textfield(recipientIban) {
|
||||||
fixedHeight = TextFieldHeight
|
fixedHeight = TextFieldHeight
|
||||||
|
|
||||||
paddingLeft = 8.0
|
paddingLeft = 8.0
|
||||||
|
|
||||||
if (this@TransferMoneyDialog.remitteeName.value.isNotBlank()) {
|
if (this@TransferMoneyDialog.recipientName.value.isNotBlank()) {
|
||||||
runLater {
|
runLater {
|
||||||
requestFocus()
|
requestFocus()
|
||||||
}
|
}
|
||||||
|
@ -162,10 +163,10 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field(messages["transfer.money.dialog.remittee.bank.label"]) {
|
field(messages["transfer.money.dialog.recipient.bank.label"]) {
|
||||||
fixedHeight = FieldHeight
|
fixedHeight = FieldHeight
|
||||||
|
|
||||||
textfield(remitteeBankName) {
|
textfield(recipientBankName) {
|
||||||
fixedHeight = TextFieldHeight
|
fixedHeight = TextFieldHeight
|
||||||
|
|
||||||
isDisable = true
|
isDisable = true
|
||||||
|
@ -174,10 +175,10 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field(messages["transfer.money.dialog.remittee.bic.label"]) {
|
field(messages["transfer.money.dialog.recipient.bic.label"]) {
|
||||||
fixedHeight = FieldHeight
|
fixedHeight = FieldHeight
|
||||||
|
|
||||||
textfield(remitteeBic) {
|
textfield(recipientBic) {
|
||||||
fixedHeight = TextFieldHeight
|
fixedHeight = TextFieldHeight
|
||||||
|
|
||||||
isDisable = true
|
isDisable = true
|
||||||
|
@ -197,7 +198,7 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
fixedWidth = 100.0
|
fixedWidth = 100.0
|
||||||
alignment = Pos.CENTER_RIGHT
|
alignment = Pos.CENTER_RIGHT
|
||||||
|
|
||||||
if (this@TransferMoneyDialog.remitteeName.value.isNotBlank() && remitteeIban.value.isNotBlank()) {
|
if (this@TransferMoneyDialog.recipientName.value.isNotBlank() && recipientIban.value.isNotBlank()) {
|
||||||
runLater {
|
runLater {
|
||||||
requestFocus()
|
requestFocus()
|
||||||
}
|
}
|
||||||
|
@ -212,10 +213,10 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field(messages["transfer.money.dialog.usage.label"]) {
|
field(messages["transfer.money.dialog.reference.label"]) {
|
||||||
fixedHeight = FieldHeight
|
fixedHeight = FieldHeight
|
||||||
|
|
||||||
textfield(usage) {
|
textfield(reference) {
|
||||||
fixedHeight = TextFieldHeight
|
fixedHeight = TextFieldHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,10 +224,10 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
field {
|
field {
|
||||||
fixedHeight = FieldHeight
|
fixedHeight = FieldHeight
|
||||||
|
|
||||||
checkbox(messages["transfer.money.dialog.instant.payment.label"], instantPayment) {
|
checkbox(messages["transfer.money.dialog.real.time.transfer.label"], realTimeTransfer) {
|
||||||
fixedHeight = TextFieldHeight
|
fixedHeight = TextFieldHeight
|
||||||
|
|
||||||
enableWhen(supportsInstantPayment)
|
enableWhen(supportsRealTimeTransfer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,37 +265,37 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tryToGetBicFromIban(remitteeIban.value)
|
tryToGetBicFromIban(recipientIban.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun selectedBankAccountChanged(newValue: TypedBankAccount?) {
|
private fun selectedBankAccountChanged(newValue: TypedBankAccount?) {
|
||||||
supportsInstantPayment.value = newValue?.supportsInstantPaymentMoneyTransfer ?: false
|
supportsRealTimeTransfer.value = newValue?.supportsRealTimeTransfer ?: false
|
||||||
|
|
||||||
if (supportsInstantPayment.value == false) {
|
if (supportsRealTimeTransfer.value == false) {
|
||||||
instantPayment.value = false
|
realTimeTransfer.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open fun searchRemittees(query: String?) {
|
protected open fun searchRecipients(query: String?) {
|
||||||
lastSearchRemitteeJob?.cancel()
|
lastSearchRecipientJob?.cancel()
|
||||||
|
|
||||||
lastSearchRemitteeJob = GlobalScope.launch(Dispatchers.IO) {
|
lastSearchRecipientJob = GlobalScope.launch(Dispatchers.IO) {
|
||||||
val potentialRemittees = presenter.findRemitteesForName(query?.toString() ?: "")
|
val potentialRecipients = presenter.findRecipientsForName(query?.toString() ?: "")
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
txtfldRemitteeName.setAutoCompleteList(potentialRemittees)
|
txtfldRecipientName.setAutoCompleteList(potentialRecipients)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun remitteeSelected(remittee: Remittee) {
|
protected open fun recipientSelected(transactionParty: TransactionParty) {
|
||||||
txtfldRemitteeName.focusNextControl()
|
txtfldRecipientName.focusNextControl()
|
||||||
|
|
||||||
remitteeName.value = remittee.name
|
recipientName.value = transactionParty.name
|
||||||
remitteeBic.value = remittee.bic
|
recipientBic.value = transactionParty.bic
|
||||||
remitteeIban.value = remittee.iban
|
recipientIban.value = transactionParty.iban
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,11 +308,11 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun showValuesForFoundBankOnUiThread(firstFoundBank: BankInfo?, enteredIban: String) {
|
protected open fun showValuesForFoundBankOnUiThread(firstFoundBank: BankInfo?, enteredIban: String) {
|
||||||
remitteeBank.value = firstFoundBank
|
recipientBank.value = firstFoundBank
|
||||||
|
|
||||||
remitteeBankName.value = determineFoundBankLabel(enteredIban, firstFoundBank)
|
recipientBankName.value = determineFoundBankLabel(enteredIban, firstFoundBank)
|
||||||
|
|
||||||
remitteeBic.value = firstFoundBank?.bic ?: messages["transfer.money.dialog.bank.name.will.be.entered.automatically"]
|
recipientBic.value = firstFoundBank?.bic ?: messages["transfer.money.dialog.bank.name.will.be.entered.automatically"]
|
||||||
|
|
||||||
checkIfRequiredDataEnteredOnUiThread()
|
checkIfRequiredDataEnteredOnUiThread()
|
||||||
}
|
}
|
||||||
|
@ -331,12 +332,12 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
|
|
||||||
protected open fun checkIfRequiredDataEnteredOnUiThread() {
|
protected open fun checkIfRequiredDataEnteredOnUiThread() {
|
||||||
requiredDataEntered.value =
|
requiredDataEntered.value =
|
||||||
remitteeName.value.isNotBlank()
|
recipientName.value.isNotBlank()
|
||||||
&& inputValidator.isRemitteeNameValid(remitteeName.value) // TODO: show error message for illegal characters
|
&& inputValidator.isRecipientNameValid(recipientName.value) // TODO: show error message for illegal characters
|
||||||
&& inputValidator.isValidIban(remitteeIban.value)
|
&& inputValidator.isValidIban(recipientIban.value)
|
||||||
&& inputValidator.isValidBic(remitteeBic.value)
|
&& inputValidator.isValidBic(recipientBic.value)
|
||||||
&& amount.value > 0
|
&& amount.value > 0
|
||||||
&& inputValidator.isUsageValid(usage.value) // TODO: show error message for illegal characters
|
&& inputValidator.isReferenceValid(reference.value) // TODO: show error message for illegal characters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -345,17 +346,17 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun transferMoney() {
|
protected open fun transferMoney() {
|
||||||
remitteeBank.value?.let {
|
recipientBank.value?.let {
|
||||||
val account = selectedBankAccount.value
|
val account = selectedBankAccount.value
|
||||||
|
|
||||||
val data = TransferMoneyData(
|
val data = TransferMoneyData(
|
||||||
account,
|
account,
|
||||||
inputValidator.convertToAllowedSepaCharacters(remitteeName.value),
|
inputValidator.convertToAllowedSepaCharacters(recipientName.value),
|
||||||
remitteeIban.value.replace(" ", ""),
|
recipientIban.value.replace(" ", ""),
|
||||||
remitteeBic.value.replace(" ", ""),
|
recipientBic.value.replace(" ", ""),
|
||||||
amount.value.toBigDecimal().toBigDecimal(),
|
amount.value.toBigDecimal().toBigDecimal(),
|
||||||
inputValidator.convertToAllowedSepaCharacters(usage.value),
|
inputValidator.convertToAllowedSepaCharacters(reference.value),
|
||||||
instantPayment.value
|
realTimeTransfer.value
|
||||||
)
|
)
|
||||||
|
|
||||||
presenter.transferMoneyAsync(data) {
|
presenter.transferMoneyAsync(data) {
|
||||||
|
@ -371,11 +372,11 @@ open class TransferMoneyDialog @JvmOverloads constructor(
|
||||||
|
|
||||||
if (response.successful) {
|
if (response.successful) {
|
||||||
dialogService.showInfoMessage(String.format(messages["transfer.money.dialog.message.transfer.cash.success"],
|
dialogService.showInfoMessage(String.format(messages["transfer.money.dialog.message.transfer.cash.success"],
|
||||||
transferData.amount, currency, transferData.creditorName), null, currentStage)
|
transferData.amount, currency, transferData.recipientName), null, currentStage)
|
||||||
}
|
}
|
||||||
else if (response.userCancelledAction == false) {
|
else if (response.userCancelledAction == false) {
|
||||||
dialogService.showErrorMessage(String.format(messages["transfer.money.dialog.message.transfer.cash.error"],
|
dialogService.showErrorMessage(String.format(messages["transfer.money.dialog.message.transfer.cash.error"],
|
||||||
transferData.amount, currency, transferData.creditorName, response.errorToShowToUser), null, null, currentStage)
|
transferData.amount, currency, transferData.recipientName, response.errorToShowToUser), null, null, currentStage)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.successful || response.userCancelledAction) { // do not close dialog if an error occurred
|
if (response.successful || response.userCancelledAction) { // do not close dialog if an error occurred
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package net.dankito.banking.search
|
|
||||||
|
|
||||||
|
|
||||||
interface IRemitteeSearcher {
|
|
||||||
|
|
||||||
fun findRemittees(query: String): List<Remittee>
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package net.dankito.banking.search
|
||||||
|
|
||||||
|
|
||||||
|
interface ITransactionPartySearcher {
|
||||||
|
|
||||||
|
fun findTransactionParty(query: String): List<TransactionParty>
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
package net.dankito.banking.search
|
|
||||||
|
|
||||||
|
|
||||||
open class NoOpRemitteeSearcher : IRemitteeSearcher {
|
|
||||||
|
|
||||||
override fun findRemittees(query: String): List<Remittee> {
|
|
||||||
return listOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.dankito.banking.search
|
||||||
|
|
||||||
|
|
||||||
|
open class NoOpTransactionPartySearcher : ITransactionPartySearcher {
|
||||||
|
|
||||||
|
override fun findTransactionParty(query: String): List<TransactionParty> {
|
||||||
|
return listOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package net.dankito.banking.search
|
package net.dankito.banking.search
|
||||||
|
|
||||||
|
|
||||||
data class Remittee(
|
data class TransactionParty(
|
||||||
val name: String,
|
val name: String,
|
||||||
val iban: String?,
|
val iban: String?,
|
||||||
val bic: String?,
|
val bic: String?,
|
||||||
|
@ -14,7 +14,7 @@ data class Remittee(
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other !is Remittee) return false
|
if (other !is TransactionParty) return false
|
||||||
|
|
||||||
if (name.equals(other.name, true) == false) return false
|
if (name.equals(other.name, true) == false) return false
|
||||||
if (iban != other.iban) return false
|
if (iban != other.iban) return false
|
|
@ -8,7 +8,7 @@ open class AccountTransaction(
|
||||||
override val account: TypedBankAccount,
|
override val account: TypedBankAccount,
|
||||||
override val amount: BigDecimal,
|
override val amount: BigDecimal,
|
||||||
override val currency: String,
|
override val currency: String,
|
||||||
override val unparsedUsage: String,
|
override val unparsedReference: String,
|
||||||
override val bookingDate: Date,
|
override val bookingDate: Date,
|
||||||
override val otherPartyName: String?,
|
override val otherPartyName: String?,
|
||||||
override val otherPartyBankCode: String?,
|
override val otherPartyBankCode: String?,
|
||||||
|
@ -27,10 +27,10 @@ open class AccountTransaction(
|
||||||
override val originatorsIdentificationCode: String?,
|
override val originatorsIdentificationCode: String?,
|
||||||
override val compensationAmount: String?,
|
override val compensationAmount: String?,
|
||||||
override val originalAmount: String?,
|
override val originalAmount: String?,
|
||||||
override val sepaUsage: String?,
|
override val sepaReference: String?,
|
||||||
override val deviantOriginator: String?,
|
override val deviantOriginator: String?,
|
||||||
override val deviantRecipient: String?,
|
override val deviantRecipient: String?,
|
||||||
override val usageWithNoSpecialType: String?,
|
override val referenceWithNoSpecialType: String?,
|
||||||
override val primaNotaNumber: String?,
|
override val primaNotaNumber: String?,
|
||||||
override val textKeySupplement: String?,
|
override val textKeySupplement: String?,
|
||||||
|
|
||||||
|
@ -49,15 +49,15 @@ open class AccountTransaction(
|
||||||
|
|
||||||
/* convenience constructors for languages not supporting default values */
|
/* convenience constructors for languages not supporting default values */
|
||||||
|
|
||||||
constructor(account: BankAccount, otherPartyName: String?, unparsedUsage: String, amount: BigDecimal, valueDate: Date, bookingText: String?)
|
constructor(account: BankAccount, otherPartyName: String?, unparsedReference: String, amount: BigDecimal, valueDate: Date, bookingText: String?)
|
||||||
: this(account, amount, "EUR", unparsedUsage, valueDate,
|
: this(account, amount, "EUR", unparsedReference, valueDate,
|
||||||
otherPartyName, null, null, bookingText, valueDate)
|
otherPartyName, null, null, bookingText, valueDate)
|
||||||
|
|
||||||
|
|
||||||
constructor(account: BankAccount, amount: BigDecimal, currency: String, unparsedUsage: String, bookingDate: Date,
|
constructor(account: BankAccount, amount: BigDecimal, currency: String, unparsedReference: String, bookingDate: Date,
|
||||||
otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?,
|
otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?,
|
||||||
bookingText: String?, valueDate: Date)
|
bookingText: String?, valueDate: Date)
|
||||||
: this(account, amount, currency, unparsedUsage, bookingDate,
|
: this(account, amount, currency, unparsedReference, bookingDate,
|
||||||
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate,
|
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate,
|
||||||
0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null, null, "", null)
|
0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null, null, "", null)
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ open class BankAccount @JvmOverloads constructor(
|
||||||
override var supportsRetrievingAccountTransactions: Boolean = false,
|
override var supportsRetrievingAccountTransactions: Boolean = false,
|
||||||
override var supportsRetrievingBalance: Boolean = false,
|
override var supportsRetrievingBalance: Boolean = false,
|
||||||
override var supportsTransferringMoney: Boolean = false,
|
override var supportsTransferringMoney: Boolean = false,
|
||||||
override var supportsInstantPaymentMoneyTransfer: Boolean = false,
|
override var supportsRealTimeTransfer: Boolean = false,
|
||||||
override var bookedTransactions: List<IAccountTransaction> = listOf(),
|
override var bookedTransactions: List<IAccountTransaction> = listOf(),
|
||||||
override var unbookedTransactions: List<Any> = listOf()
|
override var unbookedTransactions: List<Any> = listOf()
|
||||||
) : TypedBankAccount {
|
) : TypedBankAccount {
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface IAccountTransaction {
|
||||||
val account: IBankAccount<*>
|
val account: IBankAccount<*>
|
||||||
val amount: BigDecimal
|
val amount: BigDecimal
|
||||||
val currency: String
|
val currency: String
|
||||||
val unparsedUsage: String
|
val unparsedReference: String
|
||||||
val bookingDate: Date
|
val bookingDate: Date
|
||||||
val otherPartyName: String?
|
val otherPartyName: String?
|
||||||
val otherPartyBankCode: String?
|
val otherPartyBankCode: String?
|
||||||
|
@ -35,10 +35,10 @@ interface IAccountTransaction {
|
||||||
val originatorsIdentificationCode: String?
|
val originatorsIdentificationCode: String?
|
||||||
val compensationAmount: String?
|
val compensationAmount: String?
|
||||||
val originalAmount: String?
|
val originalAmount: String?
|
||||||
val sepaUsage: String?
|
val sepaReference: String?
|
||||||
val deviantOriginator: String?
|
val deviantOriginator: String?
|
||||||
val deviantRecipient: String?
|
val deviantRecipient: String?
|
||||||
val usageWithNoSpecialType: String?
|
val referenceWithNoSpecialType: String?
|
||||||
val primaNotaNumber: String?
|
val primaNotaNumber: String?
|
||||||
val textKeySupplement: String?
|
val textKeySupplement: String?
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ interface IAccountTransaction {
|
||||||
|
|
||||||
var technicalId: String
|
var technicalId: String
|
||||||
|
|
||||||
open val transactionIdentifier: String
|
val transactionIdentifier: String
|
||||||
get() = buildTransactionIdentifier()
|
get() = buildTransactionIdentifier()
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,16 +64,16 @@ interface IAccountTransaction {
|
||||||
val canCreateMoneyTransferFrom: Boolean
|
val canCreateMoneyTransferFrom: Boolean
|
||||||
get() = otherPartyAccountId != null && account.supportsTransferringMoney
|
get() = otherPartyAccountId != null && account.supportsTransferringMoney
|
||||||
|
|
||||||
val usage: String
|
val reference: String
|
||||||
get() = sepaUsage ?: unparsedUsage
|
get() = sepaReference ?: unparsedReference
|
||||||
|
|
||||||
|
|
||||||
fun buildTransactionIdentifier() : String {
|
fun buildTransactionIdentifier() : String {
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
return "${account.technicalId} ${IdDateFormat.format(bookingDate)} ${IdDateFormat.format(valueDate)} $amount $currency $unparsedUsage $otherPartyName $otherPartyBankCode $otherPartyAccountId"
|
return "${account.technicalId} ${IdDateFormat.format(bookingDate)} ${IdDateFormat.format(valueDate)} $amount $currency $unparsedReference $otherPartyName $otherPartyBankCode $otherPartyAccountId"
|
||||||
}
|
}
|
||||||
else { // happens for derived classes during initialization. These have to set technicalId after initialization by themselves
|
else { // happens for derived classes during initialization. These have to set technicalId after initialization by themselves
|
||||||
return "<uninitialized_bank_acccount> ${IdDateFormat.format(bookingDate)} ${IdDateFormat.format(valueDate)} $amount $currency $unparsedUsage $otherPartyName $otherPartyBankCode $otherPartyAccountId"
|
return "<uninitialized_bank_acccount> ${IdDateFormat.format(bookingDate)} ${IdDateFormat.format(valueDate)} $amount $currency $unparsedReference $otherPartyName $otherPartyBankCode $otherPartyAccountId"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ interface IAccountTransaction {
|
||||||
if (account != other.account) return false
|
if (account != other.account) return false
|
||||||
if (amount != other.amount) return false
|
if (amount != other.amount) return false
|
||||||
if (currency != other.currency) return false
|
if (currency != other.currency) return false
|
||||||
if (unparsedUsage != other.unparsedUsage) return false
|
if (unparsedReference != other.unparsedReference) return false
|
||||||
if (bookingDate != other.bookingDate) return false
|
if (bookingDate != other.bookingDate) return false
|
||||||
if (otherPartyName != other.otherPartyName) return false
|
if (otherPartyName != other.otherPartyName) return false
|
||||||
if (otherPartyBankCode != other.otherPartyBankCode) return false
|
if (otherPartyBankCode != other.otherPartyBankCode) return false
|
||||||
|
@ -101,7 +101,7 @@ interface IAccountTransaction {
|
||||||
var result = account.hashCode()
|
var result = account.hashCode()
|
||||||
result = 31 * result + amount.hashCode()
|
result = 31 * result + amount.hashCode()
|
||||||
result = 31 * result + currency.hashCode()
|
result = 31 * result + currency.hashCode()
|
||||||
result = 31 * result + unparsedUsage.hashCode()
|
result = 31 * result + unparsedReference.hashCode()
|
||||||
result = 31 * result + bookingDate.hashCode()
|
result = 31 * result + bookingDate.hashCode()
|
||||||
result = 31 * result + (otherPartyName?.hashCode() ?: 0)
|
result = 31 * result + (otherPartyName?.hashCode() ?: 0)
|
||||||
result = 31 * result + (otherPartyBankCode?.hashCode() ?: 0)
|
result = 31 * result + (otherPartyBankCode?.hashCode() ?: 0)
|
||||||
|
@ -112,6 +112,6 @@ interface IAccountTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
val stringRepresentation: String
|
val stringRepresentation: String
|
||||||
get() = "${DateFormatter(DateFormatStyle.Medium).format(valueDate)} $amount $otherPartyName: $usage"
|
get() = "${DateFormatter(DateFormatStyle.Medium).format(valueDate)} $amount $otherPartyName: $reference"
|
||||||
|
|
||||||
}
|
}
|
|
@ -24,7 +24,7 @@ interface IBankAccount<TTransaction: IAccountTransaction> : OrderedDisplayable {
|
||||||
var supportsRetrievingAccountTransactions: Boolean
|
var supportsRetrievingAccountTransactions: Boolean
|
||||||
var supportsRetrievingBalance: Boolean
|
var supportsRetrievingBalance: Boolean
|
||||||
var supportsTransferringMoney: Boolean
|
var supportsTransferringMoney: Boolean
|
||||||
var supportsInstantPaymentMoneyTransfer: Boolean
|
var supportsRealTimeTransfer: Boolean
|
||||||
var bookedTransactions: List<TTransaction>
|
var bookedTransactions: List<TTransaction>
|
||||||
var unbookedTransactions: List<Any>
|
var unbookedTransactions: List<Any>
|
||||||
var technicalId: String
|
var technicalId: String
|
||||||
|
|
|
@ -22,7 +22,7 @@ open class DefaultModelCreator : IModelCreator {
|
||||||
account: TypedBankAccount,
|
account: TypedBankAccount,
|
||||||
amount: BigDecimal,
|
amount: BigDecimal,
|
||||||
currency: String,
|
currency: String,
|
||||||
unparsedUsage: String,
|
unparsedReference: String,
|
||||||
bookingDate: Date,
|
bookingDate: Date,
|
||||||
otherPartyName: String?,
|
otherPartyName: String?,
|
||||||
otherPartyBankCode: String?,
|
otherPartyBankCode: String?,
|
||||||
|
@ -40,10 +40,10 @@ open class DefaultModelCreator : IModelCreator {
|
||||||
originatorsIdentificationCode: String?,
|
originatorsIdentificationCode: String?,
|
||||||
compensationAmount: String?,
|
compensationAmount: String?,
|
||||||
originalAmount: String?,
|
originalAmount: String?,
|
||||||
sepaUsage: String?,
|
sepaReference: String?,
|
||||||
deviantOriginator: String?,
|
deviantOriginator: String?,
|
||||||
deviantRecipient: String?,
|
deviantRecipient: String?,
|
||||||
usageWithNoSpecialType: String?,
|
referenceWithNoSpecialType: String?,
|
||||||
primaNotaNumber: String?,
|
primaNotaNumber: String?,
|
||||||
textKeySupplement: String?,
|
textKeySupplement: String?,
|
||||||
currencyType: String?,
|
currencyType: String?,
|
||||||
|
@ -55,11 +55,11 @@ open class DefaultModelCreator : IModelCreator {
|
||||||
relatedReferenceNumber: String?
|
relatedReferenceNumber: String?
|
||||||
) : IAccountTransaction {
|
) : IAccountTransaction {
|
||||||
|
|
||||||
return AccountTransaction(account, amount, currency, unparsedUsage, bookingDate,
|
return AccountTransaction(account, amount, currency, unparsedReference, bookingDate,
|
||||||
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate, statementNumber, sequenceNumber,
|
otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate, statementNumber, sequenceNumber,
|
||||||
openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, creditorIdentifier,
|
openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, creditorIdentifier,
|
||||||
originatorsIdentificationCode, compensationAmount, originalAmount, sepaUsage, deviantOriginator, deviantRecipient,
|
originatorsIdentificationCode, compensationAmount, originalAmount, sepaReference, deviantOriginator, deviantRecipient,
|
||||||
usageWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner,
|
referenceWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner,
|
||||||
referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber)
|
referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ interface IModelCreator {
|
||||||
account: TypedBankAccount,
|
account: TypedBankAccount,
|
||||||
amount: BigDecimal,
|
amount: BigDecimal,
|
||||||
currency: String,
|
currency: String,
|
||||||
unparsedUsage: String,
|
unparsedReference: String,
|
||||||
bookingDate: Date,
|
bookingDate: Date,
|
||||||
otherPartyName: String?,
|
otherPartyName: String?,
|
||||||
otherPartyBankCode: String?,
|
otherPartyBankCode: String?,
|
||||||
|
@ -38,10 +38,10 @@ interface IModelCreator {
|
||||||
originatorsIdentificationCode: String?,
|
originatorsIdentificationCode: String?,
|
||||||
compensationAmount: String?,
|
compensationAmount: String?,
|
||||||
originalAmount: String?,
|
originalAmount: String?,
|
||||||
sepaUsage: String?,
|
sepaReference: String?,
|
||||||
deviantOriginator: String?,
|
deviantOriginator: String?,
|
||||||
deviantRecipient: String?,
|
deviantRecipient: String?,
|
||||||
usageWithNoSpecialType: String?,
|
referenceWithNoSpecialType: String?,
|
||||||
primaNotaNumber: String?,
|
primaNotaNumber: String?,
|
||||||
textKeySupplement: String?,
|
textKeySupplement: String?,
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,17 @@ import net.dankito.utils.multiplatform.BigDecimal
|
||||||
|
|
||||||
open class TransferMoneyData(
|
open class TransferMoneyData(
|
||||||
val account: TypedBankAccount,
|
val account: TypedBankAccount,
|
||||||
val creditorName: String,
|
val recipientName: String,
|
||||||
val creditorIban: String,
|
val recipientAccountId: String,
|
||||||
val creditorBic: String,
|
val recipientBankCode: String,
|
||||||
val amount: BigDecimal,
|
val amount: BigDecimal,
|
||||||
val usage: String,
|
val reference: String,
|
||||||
val instantPayment: Boolean = false
|
val realTimeTransfer: Boolean = false
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun fromAccountTransactionWithoutAmountAndUsage(transaction: IAccountTransaction): TransferMoneyData {
|
fun fromAccountTransactionWithoutAmountAndReference(transaction: IAccountTransaction): TransferMoneyData {
|
||||||
return TransferMoneyData(
|
return TransferMoneyData(
|
||||||
transaction.account as TypedBankAccount,
|
transaction.account as TypedBankAccount,
|
||||||
transaction.otherPartyName ?: "",
|
transaction.otherPartyName ?: "",
|
||||||
|
@ -34,7 +34,7 @@ open class TransferMoneyData(
|
||||||
transaction.otherPartyAccountId ?: "",
|
transaction.otherPartyAccountId ?: "",
|
||||||
transaction.otherPartyBankCode ?: "",
|
transaction.otherPartyBankCode ?: "",
|
||||||
if (transaction.amount.isPositive) transaction.amount else transaction.amount.negated(),
|
if (transaction.amount.isPositive) transaction.amount else transaction.amount.negated(),
|
||||||
transaction.usage
|
transaction.reference
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ import net.dankito.banking.ui.model.responses.BankingClientResponse
|
||||||
import net.dankito.banking.ui.model.responses.GetTransactionsResponse
|
import net.dankito.banking.ui.model.responses.GetTransactionsResponse
|
||||||
import net.dankito.banking.bankfinder.IBankFinder
|
import net.dankito.banking.bankfinder.IBankFinder
|
||||||
import net.dankito.banking.bankfinder.BankInfo
|
import net.dankito.banking.bankfinder.BankInfo
|
||||||
import net.dankito.banking.search.IRemitteeSearcher
|
import net.dankito.banking.search.ITransactionPartySearcher
|
||||||
import net.dankito.banking.search.NoOpRemitteeSearcher
|
import net.dankito.banking.search.NoOpTransactionPartySearcher
|
||||||
import net.dankito.banking.search.Remittee
|
import net.dankito.banking.search.TransactionParty
|
||||||
import net.dankito.banking.ui.model.mapper.DefaultModelCreator
|
import net.dankito.banking.ui.model.mapper.DefaultModelCreator
|
||||||
import net.dankito.banking.ui.model.mapper.IModelCreator
|
import net.dankito.banking.ui.model.mapper.IModelCreator
|
||||||
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResult
|
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResult
|
||||||
|
@ -39,7 +39,7 @@ open class BankingPresenter(
|
||||||
protected val persister: IBankingPersistence,
|
protected val persister: IBankingPersistence,
|
||||||
protected val router: IRouter,
|
protected val router: IRouter,
|
||||||
protected val modelCreator: IModelCreator = DefaultModelCreator(),
|
protected val modelCreator: IModelCreator = DefaultModelCreator(),
|
||||||
protected val remitteeSearcher: IRemitteeSearcher = NoOpRemitteeSearcher(),
|
protected val transactionPartySearcher: ITransactionPartySearcher = NoOpTransactionPartySearcher(),
|
||||||
protected val bankIconFinder: IBankIconFinder = NoOpBankIconFinder(),
|
protected val bankIconFinder: IBankIconFinder = NoOpBankIconFinder(),
|
||||||
protected val textExtractorRegistry: ITextExtractorRegistry = NoOpTextExtractorRegistry(),
|
protected val textExtractorRegistry: ITextExtractorRegistry = NoOpTextExtractorRegistry(),
|
||||||
protected val invoiceDataExtractor: IInvoiceDataExtractor = NoOpInvoiceDataExtractor(),
|
protected val invoiceDataExtractor: IInvoiceDataExtractor = NoOpInvoiceDataExtractor(),
|
||||||
|
@ -553,16 +553,16 @@ open class BankingPresenter(
|
||||||
return bankFinder.findBankByNameBankCodeOrCity(query)
|
return bankFinder.findBankByNameBankCodeOrCity(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun findRemitteesForName(name: String): List<Remittee> {
|
open fun findRecipientsForName(name: String): List<TransactionParty> {
|
||||||
return remitteeSearcher.findRemittees(name).map { remittee ->
|
return transactionPartySearcher.findTransactionParty(name).map { recipient ->
|
||||||
remittee.bankName = tryToFindBankName(remittee)
|
recipient.bankName = tryToFindBankName(recipient)
|
||||||
|
|
||||||
remittee
|
recipient
|
||||||
}.toSet().toList()
|
}.toSet().toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun tryToFindBankName(remittee: Remittee): String? {
|
protected open fun tryToFindBankName(transactionParty: TransactionParty): String? {
|
||||||
remittee.bic?.let { bic ->
|
transactionParty.bic?.let { bic ->
|
||||||
bankFinder.findBankByBic(bic)?.name?.let {
|
bankFinder.findBankByBic(bic)?.name?.let {
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
@ -574,7 +574,7 @@ open class BankingPresenter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remittee.iban?.let { iban ->
|
transactionParty.iban?.let { iban ->
|
||||||
if (iban.length > 12) {
|
if (iban.length > 12) {
|
||||||
val bankCode = iban.substring(4, 12)
|
val bankCode = iban.substring(4, 12)
|
||||||
return bankFinder.findBankByBankCode(bankCode).firstOrNull()?.name
|
return bankFinder.findBankByBankCode(bankCode).firstOrNull()?.name
|
||||||
|
@ -598,7 +598,7 @@ open class BankingPresenter(
|
||||||
|
|
||||||
return transactions.filter {
|
return transactions.filter {
|
||||||
it.otherPartyName?.toLowerCase()?.contains(queryLowercase) == true
|
it.otherPartyName?.toLowerCase()?.contains(queryLowercase) == true
|
||||||
|| it.usage.toLowerCase().contains(queryLowercase)
|
|| it.reference.toLowerCase().contains(queryLowercase)
|
||||||
|| it.bookingText?.toLowerCase()?.contains(queryLowercase) == true
|
|| it.bookingText?.toLowerCase()?.contains(queryLowercase) == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ open class InputValidator {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val RemitteNameMaxLength = 70
|
const val RecipientNameMaxLength = 70
|
||||||
|
|
||||||
const val IbanMaxLength = 34
|
const val IbanMaxLength = 34
|
||||||
|
|
||||||
const val BicMaxLength = 11
|
const val BicMaxLength = 11
|
||||||
|
|
||||||
const val UsageMaxLength = 140
|
const val ReferenceMaxLength = 140
|
||||||
|
|
||||||
const val MinimumLengthToDetermineBicFromIban = 12 // TODO: this is only true for German (and may some other) IBANs
|
const val MinimumLengthToDetermineBicFromIban = 12 // TODO: this is only true for German (and may some other) IBANs
|
||||||
|
|
||||||
|
@ -65,45 +65,45 @@ open class InputValidator {
|
||||||
protected val sepaMessageCreator: ISepaMessageCreator = SepaMessageCreator()
|
protected val sepaMessageCreator: ISepaMessageCreator = SepaMessageCreator()
|
||||||
|
|
||||||
|
|
||||||
open fun validateRemitteeNameWhileTyping(remitteeNameToTest: String): ValidationResult {
|
open fun validateRecipientNameWhileTyping(recipientNameToTest: String): ValidationResult {
|
||||||
return validateRemitteeName(remitteeNameToTest, true)
|
return validateRecipientName(recipientNameToTest, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun validateRemitteeName(remitteeNameToTest: String): ValidationResult {
|
open fun validateRecipientName(recipientNameToTest: String): ValidationResult {
|
||||||
return validateRemitteeName(remitteeNameToTest, false)
|
return validateRecipientName(recipientNameToTest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun validateRemitteeName(remitteeNameToTest: String, userIsStillTyping: Boolean = false): ValidationResult {
|
open fun validateRecipientName(recipientNameToTest: String, userIsStillTyping: Boolean = false): ValidationResult {
|
||||||
if (isRemitteeNameValid(remitteeNameToTest)) {
|
if (isRecipientNameValid(recipientNameToTest)) {
|
||||||
return ValidationResult(remitteeNameToTest, true)
|
return ValidationResult(recipientNameToTest, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remitteeNameToTest.isEmpty()) {
|
if (recipientNameToTest.isEmpty()) {
|
||||||
if (userIsStillTyping) { // if user is still typing, don't check if something has been entered yet
|
if (userIsStillTyping) { // if user is still typing, don't check if something has been entered yet
|
||||||
return ValidationResult(remitteeNameToTest, true)
|
return ValidationResult(recipientNameToTest, true)
|
||||||
}
|
}
|
||||||
return ValidationResult(remitteeNameToTest, false, validationError = "Bitte geben Sie den Namen des Empfängers ein") // TODO: translate
|
return ValidationResult(recipientNameToTest, false, validationError = "Bitte geben Sie den Namen des Empfängers ein") // TODO: translate
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasRemitteeNameValidLength(remitteeNameToTest) == false) {
|
if (hasRecipientNameValidLength(recipientNameToTest) == false) {
|
||||||
val correctedString = remitteeNameToTest.substring(0, RemitteNameMaxLength)
|
val correctedString = recipientNameToTest.substring(0, RecipientNameMaxLength)
|
||||||
return ValidationResult(remitteeNameToTest, isRemitteeNameValid(correctedString), true, correctedString, "Name darf maximal 70 Zeichen lang sein") // TODO: translate
|
return ValidationResult(recipientNameToTest, isRecipientNameValid(correctedString), true, correctedString, "Name darf maximal 70 Zeichen lang sein") // TODO: translate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val invalidRemitteeNameCharacters = getInvalidSepaCharacters(remitteeNameToTest)
|
val invalidRecipientNameCharacters = getInvalidSepaCharacters(recipientNameToTest)
|
||||||
|
|
||||||
val correctedString = getCorrectedString(remitteeNameToTest, invalidRemitteeNameCharacters, true)
|
val correctedString = getCorrectedString(recipientNameToTest, invalidRecipientNameCharacters, true)
|
||||||
return ValidationResult(remitteeNameToTest, isRemitteeNameValid(correctedString), true, correctedString, null, "Unzulässige(s) Zeichen eingegeben: $invalidRemitteeNameCharacters") // TODO: translate
|
return ValidationResult(recipientNameToTest, isRecipientNameValid(correctedString), true, correctedString, null, "Unzulässige(s) Zeichen eingegeben: $invalidRecipientNameCharacters") // TODO: translate
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun isRemitteeNameValid(stringToTest: String): Boolean {
|
open fun isRecipientNameValid(stringToTest: String): Boolean {
|
||||||
return hasRemitteeNameValidLength(stringToTest)
|
return hasRecipientNameValidLength(stringToTest)
|
||||||
&& containsOnlyValidSepaCharacters(stringToTest)
|
&& containsOnlyValidSepaCharacters(stringToTest)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun hasRemitteeNameValidLength(stringToTest: String): Boolean {
|
open fun hasRecipientNameValidLength(stringToTest: String): Boolean {
|
||||||
return stringToTest.length in 1..RemitteNameMaxLength
|
return stringToTest.length in 1..RecipientNameMaxLength
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,29 +221,29 @@ open class InputValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun validateUsage(usageToTest: String): ValidationResult {
|
open fun validateReference(referenceToTest: String): ValidationResult {
|
||||||
if (isUsageValid(usageToTest)) {
|
if (isReferenceValid(referenceToTest)) {
|
||||||
return ValidationResult(usageToTest, true)
|
return ValidationResult(referenceToTest, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasUsageValidLength(usageToTest) == false) {
|
if (hasReferenceValidLength(referenceToTest) == false) {
|
||||||
val correctedString = usageToTest.substring(0, UsageMaxLength)
|
val correctedString = referenceToTest.substring(0, ReferenceMaxLength)
|
||||||
return ValidationResult(usageToTest, isUsageValid(correctedString), true, correctedString, "Verwendungszweck darf nur 140 Zeichen lang sein") // TODO: translate
|
return ValidationResult(referenceToTest, isReferenceValid(correctedString), true, correctedString, "Verwendungszweck darf nur 140 Zeichen lang sein") // TODO: translate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val invalidUsageCharacters = getInvalidSepaCharacters(usageToTest)
|
val invalidReferenceCharacters = getInvalidSepaCharacters(referenceToTest)
|
||||||
val correctedString = getCorrectedString(usageToTest, invalidUsageCharacters, true)
|
val correctedString = getCorrectedString(referenceToTest, invalidReferenceCharacters, true)
|
||||||
return ValidationResult(usageToTest, isUsageValid(correctedString), true, correctedString, null, "Unzulässige(s) Zeichen eingegeben: $invalidUsageCharacters") // TODO: translate return ValidationResult(remitteeNameToTest, false, validationError = "Unzulässige(s) Zeichen eingegeben: ") // TODO: translate
|
return ValidationResult(referenceToTest, isReferenceValid(correctedString), true, correctedString, null, "Unzulässige(s) Zeichen eingegeben: $invalidReferenceCharacters") // TODO: translate return ValidationResult(recipentNameToTest, false, validationError = "Unzulässige(s) Zeichen eingegeben: ") // TODO: translate
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun isUsageValid(stringToTest: String): Boolean {
|
open fun isReferenceValid(stringToTest: String): Boolean {
|
||||||
return hasUsageValidLength(stringToTest)
|
return hasReferenceValidLength(stringToTest)
|
||||||
&& containsOnlyValidSepaCharacters(stringToTest)
|
&& containsOnlyValidSepaCharacters(stringToTest)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun hasUsageValidLength(stringToTest: String): Boolean {
|
open fun hasReferenceValidLength(stringToTest: String): Boolean {
|
||||||
return stringToTest.length in 0..UsageMaxLength // usage is not a required field -> may be empty
|
return stringToTest.length in 0..ReferenceMaxLength // reference is not a required field -> may be empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ open class InputValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: do not convert XML entities in user's. User will a) not understand what happened and b) afterwards auto correction will not work anymore (i think the issue lies in used Regex: '(&\w{2,4};)').
|
// TODO: do not convert XML entities in user's. User will a) not understand what happened and b) afterwards auto correction will not work anymore (i think the issue lies in used Regex: '(&\w{2,4};)').
|
||||||
// But take converted XML entities length into account when checking if remittee's name and usage length isn't too long
|
// But take converted XML entities length into account when checking if recipient's name and reference length isn't too long
|
||||||
protected open fun getCorrectedString(inputString: String, invalidCharacters: String, convertToAllowedSepaCharacters: Boolean = false): String {
|
protected open fun getCorrectedString(inputString: String, invalidCharacters: String, convertToAllowedSepaCharacters: Boolean = false): String {
|
||||||
var correctedString = if (convertToAllowedSepaCharacters) convertToAllowedSepaCharacters(inputString) else inputString
|
var correctedString = if (convertToAllowedSepaCharacters) convertToAllowedSepaCharacters(inputString) else inputString
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,13 @@ class InputValidatorTest {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val ValidRemitteeName = "Marieke Musterfrau"
|
const val ValidRecipientName = "Marieke Musterfrau"
|
||||||
|
|
||||||
const val ValidIban = "DE11123456780987654321"
|
const val ValidIban = "DE11123456780987654321"
|
||||||
|
|
||||||
const val ValidBic = "ABCDDEBBXXX"
|
const val ValidBic = "ABCDDEBBXXX"
|
||||||
|
|
||||||
const val ValidUsage = "Usage"
|
const val ValidReference = "Reference"
|
||||||
|
|
||||||
const val InvalidSepaCharacter = "!"
|
const val InvalidSepaCharacter = "!"
|
||||||
|
|
||||||
|
@ -56,13 +56,13 @@ class InputValidatorTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateRemitteeName_EmptyStringEntered() {
|
fun validateRecipientName_EmptyStringEntered() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredName = ""
|
val enteredName = ""
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateRemitteeName(enteredName)
|
val result = underTest.validateRecipientName(enteredName)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(false)
|
expect(result.validationSuccessful).toBe(false)
|
||||||
|
@ -74,13 +74,13 @@ class InputValidatorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateRemitteeName_ValidNameEntered() {
|
fun validateRecipientName_ValidNameEntered() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredName = ValidRemitteeName
|
val enteredName = ValidRecipientName
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateRemitteeName(enteredName)
|
val result = underTest.validateRecipientName(enteredName)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
|
@ -92,50 +92,50 @@ class InputValidatorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateRemitteeName_UmlautGetsConverted() {
|
fun validateRecipientName_UmlautGetsConverted() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredName = ValidRemitteeName + InvalidUmlaut
|
val enteredName = ValidRecipientName + InvalidUmlaut
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateRemitteeName(enteredName)
|
val result = underTest.validateRecipientName(enteredName)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(true)
|
expect(result.didCorrectString).toBe(true)
|
||||||
expect(result.inputString).toBe(enteredName)
|
expect(result.inputString).toBe(enteredName)
|
||||||
expect(result.correctedInputString).toBe(ValidRemitteeName + ConvertedInvalidUmlaut)
|
expect(result.correctedInputString).toBe(ValidRecipientName + ConvertedInvalidUmlaut)
|
||||||
expect(result.validationHint?.contains(InvalidUmlaut)).toBe(true)
|
expect(result.validationHint?.contains(InvalidUmlaut)).toBe(true)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateRemitteeName_InvalidCharacterGetsRemoved() {
|
fun validateRecipientName_InvalidCharacterGetsRemoved() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredName = ValidRemitteeName + InvalidSepaCharacter
|
val enteredName = ValidRecipientName + InvalidSepaCharacter
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateRemitteeName(enteredName)
|
val result = underTest.validateRecipientName(enteredName)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(true)
|
expect(result.didCorrectString).toBe(true)
|
||||||
expect(result.inputString).toBe(enteredName)
|
expect(result.inputString).toBe(enteredName)
|
||||||
expect(result.correctedInputString).toBe(ValidRemitteeName)
|
expect(result.correctedInputString).toBe(ValidRecipientName)
|
||||||
expect(result.validationHint?.contains(InvalidSepaCharacter)).toBe(true)
|
expect(result.validationHint?.contains(InvalidSepaCharacter)).toBe(true)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateRemitteeName_TooLong() {
|
fun validateRecipientName_TooLong() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val nameWithMaxLength = IntRange(0, InputValidator.RemitteNameMaxLength - 1).map { "a" }.joinToString("")
|
val nameWithMaxLength = IntRange(0, InputValidator.RemitteNameMaxLength - 1).map { "a" }.joinToString("")
|
||||||
val enteredName = nameWithMaxLength + "a"
|
val enteredName = nameWithMaxLength + "a"
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateRemitteeName(enteredName)
|
val result = underTest.validateRecipientName(enteredName)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
|
@ -480,133 +480,133 @@ class InputValidatorTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateUsage_EmptyStringEntered() {
|
fun validateReference_EmptyStringEntered() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredUsage = ""
|
val enteredReference = ""
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateUsage(enteredUsage)
|
val result = underTest.validateReference(enteredReference)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(false)
|
expect(result.didCorrectString).toBe(false)
|
||||||
expect(result.inputString).toBe(enteredUsage)
|
expect(result.inputString).toBe(enteredReference)
|
||||||
expect(result.correctedInputString).toBe(enteredUsage)
|
expect(result.correctedInputString).toBe(enteredReference)
|
||||||
expect(result.validationHint).toBe(null)
|
expect(result.validationHint).toBe(null)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateUsage_ValidUsageEntered() {
|
fun validateReference_ValidReferenceEntered() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredUsage = ValidUsage
|
val enteredReference = ValidReference
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateUsage(enteredUsage)
|
val result = underTest.validateReference(enteredReference)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(false)
|
expect(result.didCorrectString).toBe(false)
|
||||||
expect(result.inputString).toBe(enteredUsage)
|
expect(result.inputString).toBe(enteredReference)
|
||||||
expect(result.correctedInputString).toBe(enteredUsage)
|
expect(result.correctedInputString).toBe(enteredReference)
|
||||||
expect(result.validationHint).toBe(null)
|
expect(result.validationHint).toBe(null)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateUsage_UmlautGetsConverted() {
|
fun validateReference_UmlautGetsConverted() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredUsage = ValidUsage + InvalidUmlaut
|
val enteredReference = ValidReference + InvalidUmlaut
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateUsage(enteredUsage)
|
val result = underTest.validateReference(enteredReference)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(true)
|
expect(result.didCorrectString).toBe(true)
|
||||||
expect(result.inputString).toBe(enteredUsage)
|
expect(result.inputString).toBe(enteredReference)
|
||||||
expect(result.correctedInputString).toBe(ValidUsage + ConvertedInvalidUmlaut)
|
expect(result.correctedInputString).toBe(ValidReference + ConvertedInvalidUmlaut)
|
||||||
expect(result.validationHint?.contains(InvalidUmlaut)).toBe(true)
|
expect(result.validationHint?.contains(InvalidUmlaut)).toBe(true)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateUsage_InvalidCharacterGetsRemoved() {
|
fun validateReference_InvalidCharacterGetsRemoved() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val enteredUsage = ValidUsage + InvalidSepaCharacter
|
val enteredReference = ValidReference + InvalidSepaCharacter
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateUsage(enteredUsage)
|
val result = underTest.validateReference(enteredReference)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(true)
|
expect(result.didCorrectString).toBe(true)
|
||||||
expect(result.inputString).toBe(enteredUsage)
|
expect(result.inputString).toBe(enteredReference)
|
||||||
expect(result.correctedInputString).toBe(ValidUsage)
|
expect(result.correctedInputString).toBe(ValidReference)
|
||||||
expect(result.validationHint?.contains(InvalidSepaCharacter)).toBe(true)
|
expect(result.validationHint?.contains(InvalidSepaCharacter)).toBe(true)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: does not work yet
|
// TODO: does not work yet
|
||||||
@Test
|
@Test
|
||||||
fun validateUsage_AmpersandGetsRemoved() {
|
fun validateReference_AmpersandGetsRemoved() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val invalidSepaCharacter = "&"
|
val invalidSepaCharacter = "&"
|
||||||
val enteredUsage = ValidUsage + invalidSepaCharacter
|
val enteredReference = ValidReference + invalidSepaCharacter
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateUsage(enteredUsage)
|
val result = underTest.validateReference(enteredReference)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(true)
|
expect(result.didCorrectString).toBe(true)
|
||||||
expect(result.inputString).toBe(enteredUsage)
|
expect(result.inputString).toBe(enteredReference)
|
||||||
expect(result.correctedInputString).toBe(ValidUsage)
|
expect(result.correctedInputString).toBe(ValidReference)
|
||||||
expect(result.validationHint?.contains(invalidSepaCharacter)).toBe(true)
|
expect(result.validationHint?.contains(invalidSepaCharacter)).toBe(true)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: does not work yet
|
// TODO: does not work yet
|
||||||
@Test
|
@Test
|
||||||
fun validateUsage_EnteringACharacterAfterConvertingAXmlEntityDoesNotFail() {
|
fun validateReference_EnteringACharacterAfterConvertingAXmlEntityDoesNotFail() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val convertedXmlEntity = "&"
|
val convertedXmlEntity = "&"
|
||||||
val validSepaCharacter = "h"
|
val validSepaCharacter = "h"
|
||||||
val enteredUsage = ValidUsage + convertedXmlEntity + validSepaCharacter
|
val enteredReference = ValidReference + convertedXmlEntity + validSepaCharacter
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateUsage(enteredUsage)
|
val result = underTest.validateReference(enteredReference)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(true)
|
expect(result.didCorrectString).toBe(true)
|
||||||
expect(result.inputString).toBe(enteredUsage)
|
expect(result.inputString).toBe(enteredReference)
|
||||||
expect(result.correctedInputString).toBe(ValidUsage + convertedXmlEntity + validSepaCharacter)
|
expect(result.correctedInputString).toBe(ValidReference + convertedXmlEntity + validSepaCharacter)
|
||||||
expect(result.validationHint).toBe(null)
|
expect(result.validationHint).toBe(null)
|
||||||
expect(result.validationError).toBe(null)
|
expect(result.validationError).toBe(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun validateUsage_TooLong() {
|
fun validateReference_TooLong() {
|
||||||
|
|
||||||
// given
|
// given
|
||||||
val usageWithMaxLength = IntRange(0, InputValidator.UsageMaxLength - 1).map { "a" }.joinToString("")
|
val referenceWithMaxLength = IntRange(0, InputValidator.ReferenceMaxLength - 1).map { "a" }.joinToString("")
|
||||||
val enteredUsage = usageWithMaxLength + "a"
|
val enteredReference = referenceWithMaxLength + "a"
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = underTest.validateUsage(enteredUsage)
|
val result = underTest.validateReference(enteredReference)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(result.validationSuccessful).toBe(true)
|
expect(result.validationSuccessful).toBe(true)
|
||||||
expect(result.didCorrectString).toBe(true)
|
expect(result.didCorrectString).toBe(true)
|
||||||
expect(result.inputString).toBe(enteredUsage)
|
expect(result.inputString).toBe(enteredReference)
|
||||||
expect(result.correctedInputString).toBe(usageWithMaxLength)
|
expect(result.correctedInputString).toBe(referenceWithMaxLength)
|
||||||
expect(result.validationHint).toBe(null)
|
expect(result.validationHint).toBe(null)
|
||||||
expect(result.validationError).notToBeNull()
|
expect(result.validationError).notToBeNull()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package net.dankito.banking
|
||||||
import net.dankito.banking.bankfinder.InMemoryBankFinder
|
import net.dankito.banking.bankfinder.InMemoryBankFinder
|
||||||
import net.dankito.banking.fints.webclient.IWebClient
|
import net.dankito.banking.fints.webclient.IWebClient
|
||||||
import net.dankito.banking.persistence.IBankingPersistence
|
import net.dankito.banking.persistence.IBankingPersistence
|
||||||
import net.dankito.banking.search.IRemitteeSearcher
|
import net.dankito.banking.search.ITransactionPartySearcher
|
||||||
import net.dankito.banking.ui.IRouter
|
import net.dankito.banking.ui.IRouter
|
||||||
import net.dankito.banking.ui.model.mapper.DefaultModelCreator
|
import net.dankito.banking.ui.model.mapper.DefaultModelCreator
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
|
@ -14,8 +14,8 @@ import net.dankito.utils.multiplatform.File
|
||||||
|
|
||||||
|
|
||||||
class BankingPresenterSwift(dataFolder: File, router: IRouter, webClient: IWebClient, persistence: IBankingPersistence,
|
class BankingPresenterSwift(dataFolder: File, router: IRouter, webClient: IWebClient, persistence: IBankingPersistence,
|
||||||
remitteeSearcher: IRemitteeSearcher, bankIconFinder: IBankIconFinder, serializer: ISerializer, asyncRunner: IAsyncRunner)
|
transactionPartySearcher: ITransactionPartySearcher, bankIconFinder: IBankIconFinder, serializer: ISerializer, asyncRunner: IAsyncRunner)
|
||||||
: BankingPresenter(fints4kBankingClientCreator(DefaultModelCreator(), serializer, webClient), InMemoryBankFinder(), dataFolder, persistence, router, DefaultModelCreator(),
|
: BankingPresenter(fints4kBankingClientCreator(DefaultModelCreator(), serializer, webClient), InMemoryBankFinder(), dataFolder, persistence, router, DefaultModelCreator(),
|
||||||
remitteeSearcher, bankIconFinder, NoOpTextExtractorRegistry(), NoOpInvoiceDataExtractor(), serializer, asyncRunner) {
|
transactionPartySearcher, bankIconFinder, NoOpTextExtractorRegistry(), NoOpInvoiceDataExtractor(), serializer, asyncRunner) {
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,11 +28,11 @@
|
||||||
3642F01425018BA9005186FE /* TabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F01325018BA9005186FE /* TabBarController.swift */; };
|
3642F01425018BA9005186FE /* TabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F01325018BA9005186FE /* TabBarController.swift */; };
|
||||||
3642F01625018DA1005186FE /* InterceptTabClickViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F01525018DA1005186FE /* InterceptTabClickViewController.swift */; };
|
3642F01625018DA1005186FE /* InterceptTabClickViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F01525018DA1005186FE /* InterceptTabClickViewController.swift */; };
|
||||||
3642F0182502723A005186FE /* UIKitButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F0172502723A005186FE /* UIKitButton.swift */; };
|
3642F0182502723A005186FE /* UIKitButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F0172502723A005186FE /* UIKitButton.swift */; };
|
||||||
3642F01A2502931F005186FE /* InstantPaymentInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F0192502931F005186FE /* InstantPaymentInfoView.swift */; };
|
3642F01A2502931F005186FE /* RealTimeTransferInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F0192502931F005186FE /* RealTimeTransferInfoView.swift */; };
|
||||||
3642F04B25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */; };
|
3642F04B25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */; };
|
||||||
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4D924C472A90094F009 /* Extensions.swift */; };
|
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4D924C472A90094F009 /* Extensions.swift */; };
|
||||||
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DB24C479120094F009 /* BankInfoListItem.swift */; };
|
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DB24C479120094F009 /* BankInfoListItem.swift */; };
|
||||||
366FA4E024C4924A0094F009 /* RemitteeListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */; };
|
366FA4E024C4924A0094F009 /* RecipientListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DF24C4924A0094F009 /* RecipientListItem.swift */; };
|
||||||
366FA4E224C4ED6C0094F009 /* EnterTanDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4E124C4ED6C0094F009 /* EnterTanDialog.swift */; };
|
366FA4E224C4ED6C0094F009 /* EnterTanDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4E124C4ED6C0094F009 /* EnterTanDialog.swift */; };
|
||||||
366FA4E624C6EBF40094F009 /* EnterTanState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4E524C6EBF40094F009 /* EnterTanState.swift */; };
|
366FA4E624C6EBF40094F009 /* EnterTanState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4E524C6EBF40094F009 /* EnterTanState.swift */; };
|
||||||
3684EB8B2508F6F00001139E /* SearchBarWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3684EB8A2508F6F00001139E /* SearchBarWithLabel.swift */; };
|
3684EB8B2508F6F00001139E /* SearchBarWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3684EB8A2508F6F00001139E /* SearchBarWithLabel.swift */; };
|
||||||
|
@ -175,11 +175,11 @@
|
||||||
3642F01325018BA9005186FE /* TabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarController.swift; sourceTree = "<group>"; };
|
3642F01325018BA9005186FE /* TabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarController.swift; sourceTree = "<group>"; };
|
||||||
3642F01525018DA1005186FE /* InterceptTabClickViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterceptTabClickViewController.swift; sourceTree = "<group>"; };
|
3642F01525018DA1005186FE /* InterceptTabClickViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterceptTabClickViewController.swift; sourceTree = "<group>"; };
|
||||||
3642F0172502723A005186FE /* UIKitButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitButton.swift; sourceTree = "<group>"; };
|
3642F0172502723A005186FE /* UIKitButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitButton.swift; sourceTree = "<group>"; };
|
||||||
3642F0192502931F005186FE /* InstantPaymentInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantPaymentInfoView.swift; sourceTree = "<group>"; };
|
3642F0192502931F005186FE /* RealTimeTransferInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealTimeTransferInfoView.swift; sourceTree = "<group>"; };
|
||||||
3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderWithRightAlignedEditButton.swift; sourceTree = "<group>"; };
|
3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderWithRightAlignedEditButton.swift; sourceTree = "<group>"; };
|
||||||
366FA4D924C472A90094F009 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
366FA4D924C472A90094F009 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
||||||
366FA4DB24C479120094F009 /* BankInfoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankInfoListItem.swift; sourceTree = "<group>"; };
|
366FA4DB24C479120094F009 /* BankInfoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankInfoListItem.swift; sourceTree = "<group>"; };
|
||||||
366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemitteeListItem.swift; sourceTree = "<group>"; };
|
366FA4DF24C4924A0094F009 /* RecipientListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientListItem.swift; sourceTree = "<group>"; };
|
||||||
366FA4E124C4ED6C0094F009 /* EnterTanDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterTanDialog.swift; sourceTree = "<group>"; };
|
366FA4E124C4ED6C0094F009 /* EnterTanDialog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterTanDialog.swift; sourceTree = "<group>"; };
|
||||||
366FA4E524C6EBF40094F009 /* EnterTanState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterTanState.swift; sourceTree = "<group>"; };
|
366FA4E524C6EBF40094F009 /* EnterTanState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterTanState.swift; sourceTree = "<group>"; };
|
||||||
3684EB8A2508F6F00001139E /* SearchBarWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarWithLabel.swift; sourceTree = "<group>"; };
|
3684EB8A2508F6F00001139E /* SearchBarWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarWithLabel.swift; sourceTree = "<group>"; };
|
||||||
|
@ -340,7 +340,7 @@
|
||||||
36BCF88424C098C8005BEC29 /* BankAccountListItem.swift */,
|
36BCF88424C098C8005BEC29 /* BankAccountListItem.swift */,
|
||||||
36BE066424CDE62800CBBB68 /* AccountTransactionListItem.swift */,
|
36BE066424CDE62800CBBB68 /* AccountTransactionListItem.swift */,
|
||||||
366FA4DB24C479120094F009 /* BankInfoListItem.swift */,
|
366FA4DB24C479120094F009 /* BankInfoListItem.swift */,
|
||||||
366FA4DF24C4924A0094F009 /* RemitteeListItem.swift */,
|
366FA4DF24C4924A0094F009 /* RecipientListItem.swift */,
|
||||||
36E21EDE24DCCC2700649DC8 /* CheckmarkListItem.swift */,
|
36E21EDE24DCCC2700649DC8 /* CheckmarkListItem.swift */,
|
||||||
);
|
);
|
||||||
path = listitems;
|
path = listitems;
|
||||||
|
@ -552,7 +552,7 @@
|
||||||
36BE06B424CF85A300CBBB68 /* AmountLabel.swift */,
|
36BE06B424CF85A300CBBB68 /* AmountLabel.swift */,
|
||||||
360782CE24F3D6610098FEFE /* InfoLabel.swift */,
|
360782CE24F3D6610098FEFE /* InfoLabel.swift */,
|
||||||
360782C224E49FF70098FEFE /* ValidationLabel.swift */,
|
360782C224E49FF70098FEFE /* ValidationLabel.swift */,
|
||||||
3642F0192502931F005186FE /* InstantPaymentInfoView.swift */,
|
3642F0192502931F005186FE /* RealTimeTransferInfoView.swift */,
|
||||||
36BE065C24CB08FB00CBBB68 /* LazyView.swift */,
|
36BE065C24CB08FB00CBBB68 /* LazyView.swift */,
|
||||||
36C4009A24D2F9E4005227AD /* IconedTitleView.swift */,
|
36C4009A24D2F9E4005227AD /* IconedTitleView.swift */,
|
||||||
36E21ECE24DA0EEE00649DC8 /* IconView.swift */,
|
36E21ECE24DA0EEE00649DC8 /* IconView.swift */,
|
||||||
|
@ -756,7 +756,7 @@
|
||||||
360782D124F3F4120098FEFE /* SelectorWrapper.swift in Sources */,
|
360782D124F3F4120098FEFE /* SelectorWrapper.swift in Sources */,
|
||||||
36BE06BA24D0783900CBBB68 /* FaviconFinder.swift in Sources */,
|
36BE06BA24D0783900CBBB68 /* FaviconFinder.swift in Sources */,
|
||||||
36BCF89524C31F02005BEC29 /* AppData.swift in Sources */,
|
36BCF89524C31F02005BEC29 /* AppData.swift in Sources */,
|
||||||
3642F01A2502931F005186FE /* InstantPaymentInfoView.swift in Sources */,
|
3642F01A2502931F005186FE /* RealTimeTransferInfoView.swift in Sources */,
|
||||||
36B8A44F2503D97D00C15359 /* AuthenticationType.swift in Sources */,
|
36B8A44F2503D97D00C15359 /* AuthenticationType.swift in Sources */,
|
||||||
36E21EDD24DCA89100649DC8 /* TanMethodPicker.swift in Sources */,
|
36E21EDD24DCA89100649DC8 /* TanMethodPicker.swift in Sources */,
|
||||||
3608D6C624FBAB41006C93A8 /* TanGeneratorPositionMarker.swift in Sources */,
|
3608D6C624FBAB41006C93A8 /* TanGeneratorPositionMarker.swift in Sources */,
|
||||||
|
@ -771,7 +771,7 @@
|
||||||
36E21EDF24DCCC2700649DC8 /* CheckmarkListItem.swift in Sources */,
|
36E21EDF24DCCC2700649DC8 /* CheckmarkListItem.swift in Sources */,
|
||||||
36E7BA1424B3D05C00757859 /* ViewExtensions.swift in Sources */,
|
36E7BA1424B3D05C00757859 /* ViewExtensions.swift in Sources */,
|
||||||
36BCF88924C0A7D7005BEC29 /* Message.swift in Sources */,
|
36BCF88924C0A7D7005BEC29 /* Message.swift in Sources */,
|
||||||
366FA4E024C4924A0094F009 /* RemitteeListItem.swift in Sources */,
|
366FA4E024C4924A0094F009 /* RecipientListItem.swift in Sources */,
|
||||||
3608D6C224FBA9C6006C93A8 /* TrianglePointingDown.swift in Sources */,
|
3608D6C224FBA9C6006C93A8 /* TrianglePointingDown.swift in Sources */,
|
||||||
36B8A4582503EEB600C15359 /* ActionSheet.swift in Sources */,
|
36B8A4582503EEB600C15359 /* ActionSheet.swift in Sources */,
|
||||||
36BE068B24CE3B0400CBBB68 /* SwiftExtensions.swift in Sources */,
|
36BE068B24CE3B0400CBBB68 /* SwiftExtensions.swift in Sources */,
|
||||||
|
|
|
@ -24,15 +24,15 @@
|
||||||
<attribute name="primaNotaNumber" optional="YES" attributeType="String"/>
|
<attribute name="primaNotaNumber" optional="YES" attributeType="String"/>
|
||||||
<attribute name="referenceForTheAccountOwner" attributeType="String"/>
|
<attribute name="referenceForTheAccountOwner" attributeType="String"/>
|
||||||
<attribute name="referenceOfTheAccountServicingInstitution" optional="YES" attributeType="String"/>
|
<attribute name="referenceOfTheAccountServicingInstitution" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="referenceWithNoSpecialType" optional="YES" attributeType="String"/>
|
||||||
<attribute name="relatedReferenceNumber" optional="YES" attributeType="String"/>
|
<attribute name="relatedReferenceNumber" optional="YES" attributeType="String"/>
|
||||||
<attribute name="sepaUsage" optional="YES" attributeType="String"/>
|
<attribute name="sepaReference" optional="YES" attributeType="String"/>
|
||||||
<attribute name="sequenceNumber" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
<attribute name="sequenceNumber" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||||
<attribute name="statementNumber" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
<attribute name="statementNumber" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||||
<attribute name="supplementaryDetails" optional="YES" attributeType="String"/>
|
<attribute name="supplementaryDetails" optional="YES" attributeType="String"/>
|
||||||
<attribute name="textKeySupplement" optional="YES" attributeType="String"/>
|
<attribute name="textKeySupplement" optional="YES" attributeType="String"/>
|
||||||
<attribute name="transactionReferenceNumber" attributeType="String"/>
|
<attribute name="transactionReferenceNumber" attributeType="String"/>
|
||||||
<attribute name="unparsedUsage" attributeType="String"/>
|
<attribute name="unparsedReference" attributeType="String"/>
|
||||||
<attribute name="usageWithNoSpecialType" optional="YES" attributeType="String"/>
|
|
||||||
<attribute name="valueDate" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="valueDate" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistedBankAccount" inverseName="transactions" inverseEntity="PersistedBankAccount"/>
|
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PersistedBankAccount" inverseName="transactions" inverseEntity="PersistedBankAccount"/>
|
||||||
</entity>
|
</entity>
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
<attribute name="retrievedTransactionsFromOn" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="retrievedTransactionsFromOn" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<attribute name="retrievedTransactionsUpTo" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="retrievedTransactionsUpTo" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<attribute name="subAccountNumber" optional="YES" attributeType="String"/>
|
<attribute name="subAccountNumber" optional="YES" attributeType="String"/>
|
||||||
<attribute name="supportsInstantPaymentMoneyTransfer" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
<attribute name="supportsRealTimeTransfer" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||||
<attribute name="supportsRetrievingAccountTransactions" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
<attribute name="supportsRetrievingAccountTransactions" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||||
<attribute name="supportsRetrievingBalance" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
<attribute name="supportsRetrievingBalance" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||||
<attribute name="supportsTransferringMoney" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
<attribute name="supportsTransferringMoney" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||||
|
|
|
@ -101,20 +101,20 @@
|
||||||
/* TransferMoneyDialog */
|
/* TransferMoneyDialog */
|
||||||
|
|
||||||
"Transfer Money Dialog Title" = "Bank transfer";
|
"Transfer Money Dialog Title" = "Bank transfer";
|
||||||
"Remittee Name" = "Name";
|
"Recipient Name" = "Name";
|
||||||
"Remittee IBAN" = "IBAN";
|
"Recipient IBAN" = "IBAN";
|
||||||
"BIC: %@, %@" = "BIC: %@, %@";
|
"BIC: %@, %@" = "BIC: %@, %@";
|
||||||
"No BIC found for bank code %@" = "No BIC found for bank code %@";
|
"No BIC found for bank code %@" = "No BIC found for bank code %@";
|
||||||
"Amount" = "Amount";
|
"Amount" = "Amount";
|
||||||
"Usage" = "Usage";
|
"Reference" = "Reference";
|
||||||
"Enter usage" = "Optionally enter usage";
|
"Enter reference" = "Optionally enter reference";
|
||||||
|
|
||||||
"Instant Payment" = "Instant Payment";
|
"Real-time transfer" = "Real-time transfer";
|
||||||
"may with costs" = "may with costs";
|
"may with costs" = "may with costs";
|
||||||
"Instant payment information" = "Bank transfers are usually credited within one business day. However, this only applies during bank business hours, and therefore not at weekends and on public holidays. In addition, business hours vary from bank to bank. Mostly they are from 10 - 18 o'clock, sometimes also until 22 o'clock, but sometimes (e. g. Fridays) only until 14 o'clock.\n
|
"Real-time transfer information" = "Bank transfers are usually credited within one business day. However, this only applies during bank business hours, and therefore not at weekends and on public holidays. In addition, business hours vary from bank to bank. Mostly they are from 10 - 18 o'clock, sometimes also until 22 o'clock, but sometimes (e. g. Fridays) only until 14 o'clock.\n
|
||||||
Instant payment transfers on the other hand are transferred within a maximum of 10 seconds, regardless of the day and time of day.\n
|
Real-time transfers on the other hand are transferred within a maximum of 10 seconds, regardless of the day and time of day.\n
|
||||||
However, real-time transfers are often subject to a fee.\n
|
However, real-time transfers are often subject to a fee.\n
|
||||||
Unfortunately, Bankmeister cannot know whether a bank charges for instant payment transfers. Please refer to the list of prices and services of your bank.";
|
Unfortunately, Bankmeister cannot know whether a bank charges for real-time transfers. Please refer to the list of prices and services of your bank.";
|
||||||
|
|
||||||
"Transfer Money" = "Transfer";
|
"Transfer Money" = "Transfer";
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ Unfortunately, Bankmeister cannot know whether a bank charges for instant paymen
|
||||||
"Supports Retrieving Balance" = "Retrieve balance";
|
"Supports Retrieving Balance" = "Retrieve balance";
|
||||||
"Supports Retrieving Account Transactions" = "Retrieve transactions";
|
"Supports Retrieving Account Transactions" = "Retrieve transactions";
|
||||||
"Supports Transferring Money" = "Transfer money";
|
"Supports Transferring Money" = "Transfer money";
|
||||||
"Supports Instant payment transfer" = "Instant payment transfer";
|
"Supports Real-time transfer" = "Real-time transfer";
|
||||||
|
|
||||||
|
|
||||||
/* ProtectAppSettingsDialog */
|
/* ProtectAppSettingsDialog */
|
||||||
|
|
|
@ -47,7 +47,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
let dataFolder = URL(fileURLWithPath: "data", isDirectory: true, relativeTo: URL(fileURLWithPath: appDataFolder))
|
let dataFolder = URL(fileURLWithPath: "data", isDirectory: true, relativeTo: URL(fileURLWithPath: appDataFolder))
|
||||||
|
|
||||||
let presenter = BankingPresenterSwift(dataFolder: dataFolder, router: SwiftUiRouter(), webClient: UrlSessionWebClient(), persistence: persistence, remitteeSearcher: persistence, bankIconFinder: SwiftBankIconFinder(), serializer: NoOpSerializer(), asyncRunner: DispatchQueueAsyncRunner())
|
let presenter = BankingPresenterSwift(dataFolder: dataFolder, router: SwiftUiRouter(), webClient: UrlSessionWebClient(), persistence: persistence, transactionPartySearcher: persistence, bankIconFinder: SwiftBankIconFinder(), serializer: NoOpSerializer(), asyncRunner: DispatchQueueAsyncRunner())
|
||||||
|
|
||||||
DependencyInjector.register(dependency: persistence)
|
DependencyInjector.register(dependency: persistence)
|
||||||
DependencyInjector.register(dependency: presenter)
|
DependencyInjector.register(dependency: presenter)
|
||||||
|
|
|
@ -101,17 +101,17 @@
|
||||||
/* TransferMoneyDialog */
|
/* TransferMoneyDialog */
|
||||||
|
|
||||||
"Transfer Money Dialog Title" = "Überweisung";
|
"Transfer Money Dialog Title" = "Überweisung";
|
||||||
"Remittee Name" = "Name";
|
"Recipient Name" = "Name";
|
||||||
"Remittee IBAN" = "IBAN";
|
"Recipient IBAN" = "IBAN";
|
||||||
"BIC: %@, %@" = "BIC: %@, %@";
|
"BIC: %@, %@" = "BIC: %@, %@";
|
||||||
"No BIC found for bank code %@" = "Keine BIC gefunden für BLZ %@";
|
"No BIC found for bank code %@" = "Keine BIC gefunden für BLZ %@";
|
||||||
"Amount" = "Betrag";
|
"Amount" = "Betrag";
|
||||||
"Usage" = "Verwendungszweck";
|
"Reference" = "Verwendungszweck";
|
||||||
"Enter usage" = "Optional einen Verwendungszweck eingeben";
|
"Enter reference" = "Optional einen Verwendungszweck eingeben";
|
||||||
|
|
||||||
"Instant Payment" = "Echtzeitüberweisung";
|
"Real-time transfer" = "Echtzeitüberweisung";
|
||||||
"may with costs" = "evtl. kostenpflichtig";
|
"may with costs" = "evtl. kostenpflichtig";
|
||||||
"Instant payment information" = "Normale Überweisungen werden in der Regel innerhalb eines Werktages gutgeschrieben. Dies gilt jedoch nur zu Geschäftszeiten der Banken, also schon mal nicht am Wochenende und an Feiertagen. Zudem unterscheiden sich die Geschäftszeiten von Bank zu Bank. Meistens gehen diese von 10 - 18 Uhr, manchmal auch bis 22 Uhr, manchmal (Freitags) aber auch nur bis 14 Uhr.\n
|
"Real-time transfer information" = "Normale Überweisungen werden in der Regel innerhalb eines Werktages gutgeschrieben. Dies gilt jedoch nur zu Geschäftszeiten der Banken, also schon mal nicht am Wochenende und an Feiertagen. Zudem unterscheiden sich die Geschäftszeiten von Bank zu Bank. Meistens gehen diese von 10 - 18 Uhr, manchmal auch bis 22 Uhr, manchmal (Freitags) aber auch nur bis 14 Uhr.\n
|
||||||
Echtzeitüberweisungen werden hingegen innerhalb von maximal 10 Sekunden überwiesen, egal an welchem Tag und zu welcher Uhrzeit.\n
|
Echtzeitüberweisungen werden hingegen innerhalb von maximal 10 Sekunden überwiesen, egal an welchem Tag und zu welcher Uhrzeit.\n
|
||||||
Häufig sind Echtzeitüberweisungen jedoch kostenpflichtig.\n
|
Häufig sind Echtzeitüberweisungen jedoch kostenpflichtig.\n
|
||||||
Ob eine Bank Gebühren für Echtzeitüberweisungen erhebt, kann Bankmeister leider nicht wissen. Dies entnehmen Sie bitte dem Preis- / Leistungsverzeichnis Ihrer Bank.";
|
Ob eine Bank Gebühren für Echtzeitüberweisungen erhebt, kann Bankmeister leider nicht wissen. Dies entnehmen Sie bitte dem Preis- / Leistungsverzeichnis Ihrer Bank.";
|
||||||
|
@ -170,7 +170,7 @@ Ob eine Bank Gebühren für Echtzeitüberweisungen erhebt, kann Bankmeister leid
|
||||||
"Supports Retrieving Balance" = "Kontostand abrufen";
|
"Supports Retrieving Balance" = "Kontostand abrufen";
|
||||||
"Supports Retrieving Account Transactions" = "Kontoumsätze abrufen";
|
"Supports Retrieving Account Transactions" = "Kontoumsätze abrufen";
|
||||||
"Supports Transferring Money" = "Überweisen";
|
"Supports Transferring Money" = "Überweisen";
|
||||||
"Supports Instant payment transfer" = "Echtzeitüberweisung";
|
"Supports Real-time transfer" = "Echtzeitüberweisung";
|
||||||
|
|
||||||
|
|
||||||
/* ProtectAppSettingsDialog */
|
/* ProtectAppSettingsDialog */
|
||||||
|
|
|
@ -159,7 +159,7 @@ extension BankInfo : Identifiable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension Remittee : Identifiable {
|
extension TransactionParty : Identifiable {
|
||||||
|
|
||||||
public var id: String { name.localizedLowercase + "_" + (iban ?? "") }
|
public var id: String { name.localizedLowercase + "_" + (iban ?? "") }
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import UIKit
|
||||||
import BankingUiSwift
|
import BankingUiSwift
|
||||||
|
|
||||||
|
|
||||||
class CoreDataBankingPersistence: IBankingPersistence, IRemitteeSearcher {
|
class CoreDataBankingPersistence: IBankingPersistence, ITransactionPartySearcher {
|
||||||
|
|
||||||
private let mapper = Mapper()
|
private let mapper = Mapper()
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ class CoreDataBankingPersistence: IBankingPersistence, IRemitteeSearcher {
|
||||||
return UserDefaults.standard.data(forKey: filePath)
|
return UserDefaults.standard.data(forKey: filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func findRemittees(query: String) -> [Remittee] {
|
func findTransactionParty(query: String) -> [TransactionParty] {
|
||||||
var transactions: [PersistedAccountTransaction] = []
|
var transactions: [PersistedAccountTransaction] = []
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -140,13 +140,13 @@ class CoreDataBankingPersistence: IBankingPersistence, IRemitteeSearcher {
|
||||||
NSLog("Could not request banks: \(error)")
|
NSLog("Could not request banks: \(error)")
|
||||||
}
|
}
|
||||||
|
|
||||||
let remittees = transactions
|
let transactionParties = transactions
|
||||||
.filter { $0.otherPartyAccountId != nil } // if IBAN is not set we cannot make use of it
|
.filter { $0.otherPartyAccountId != nil } // if IBAN is not set we cannot make use of it
|
||||||
.map( { Remittee(name: $0.otherPartyName ?? "", iban: $0.otherPartyAccountId, bic: $0.otherPartyBankCode, bankName: nil) } )
|
.map( { TransactionParty(name: $0.otherPartyName ?? "", iban: $0.otherPartyAccountId, bic: $0.otherPartyBankCode, bankName: nil) } )
|
||||||
|
|
||||||
let uniqueRemittees = Set<Remittee>(remittees)
|
let uniqueTransactionParties = Set<TransactionParty>(transactionParties)
|
||||||
|
|
||||||
return Array(uniqueRemittees)
|
return Array(uniqueTransactionParties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ class Mapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
func map(_ bank: IBankData, _ account: PersistedBankAccount) -> IBankAccount {
|
func map(_ bank: IBankData, _ account: PersistedBankAccount) -> IBankAccount {
|
||||||
let mapped = BankAccount(bank: bank, identifier: map(account.identifier), accountHolderName: map(account.accountHolderName), iban: account.iban, subAccountNumber: account.subAccountNumber, customerId: map(account.customerId), balance: map(account.balance), currency: map(account.currency), type: map(account.type), productName: account.productName, accountLimit: account.accountLimit, retrievedTransactionsFromOn: map(account.retrievedTransactionsFromOn), retrievedTransactionsUpTo: map(account.retrievedTransactionsUpTo), supportsRetrievingAccountTransactions: account.supportsRetrievingAccountTransactions, supportsRetrievingBalance: account.supportsRetrievingBalance, supportsTransferringMoney: account.supportsTransferringMoney, supportsInstantPaymentMoneyTransfer: account.supportsInstantPaymentMoneyTransfer, bookedTransactions: [], unbookedTransactions: [])
|
let mapped = BankAccount(bank: bank, identifier: map(account.identifier), accountHolderName: map(account.accountHolderName), iban: account.iban, subAccountNumber: account.subAccountNumber, customerId: map(account.customerId), balance: map(account.balance), currency: map(account.currency), type: map(account.type), productName: account.productName, accountLimit: account.accountLimit, retrievedTransactionsFromOn: map(account.retrievedTransactionsFromOn), retrievedTransactionsUpTo: map(account.retrievedTransactionsUpTo), supportsRetrievingAccountTransactions: account.supportsRetrievingAccountTransactions, supportsRetrievingBalance: account.supportsRetrievingBalance, supportsTransferringMoney: account.supportsTransferringMoney, supportsRealTimeTransfer: account.supportsRealTimeTransfer, bookedTransactions: [], unbookedTransactions: [])
|
||||||
|
|
||||||
mapped.haveAllTransactionsBeenFetched = account.haveAllTransactionsBeenFetched
|
mapped.haveAllTransactionsBeenFetched = account.haveAllTransactionsBeenFetched
|
||||||
mapped.isAccountTypeSupported = account.isAccountTypeSupported
|
mapped.isAccountTypeSupported = account.isAccountTypeSupported
|
||||||
|
@ -97,7 +97,7 @@ class Mapper {
|
||||||
mapped.supportsRetrievingAccountTransactions = account.supportsRetrievingAccountTransactions
|
mapped.supportsRetrievingAccountTransactions = account.supportsRetrievingAccountTransactions
|
||||||
mapped.supportsRetrievingBalance = account.supportsRetrievingBalance
|
mapped.supportsRetrievingBalance = account.supportsRetrievingBalance
|
||||||
mapped.supportsTransferringMoney = account.supportsTransferringMoney
|
mapped.supportsTransferringMoney = account.supportsTransferringMoney
|
||||||
mapped.supportsInstantPaymentMoneyTransfer = account.supportsInstantPaymentMoneyTransfer
|
mapped.supportsRealTimeTransfer = account.supportsRealTimeTransfer
|
||||||
|
|
||||||
mapped.haveAllTransactionsBeenFetched = account.haveAllTransactionsBeenFetched
|
mapped.haveAllTransactionsBeenFetched = account.haveAllTransactionsBeenFetched
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ class Mapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
func map(_ account: IBankAccount, _ transaction: PersistedAccountTransaction) -> IAccountTransaction {
|
func map(_ account: IBankAccount, _ transaction: PersistedAccountTransaction) -> IAccountTransaction {
|
||||||
let mapped = AccountTransaction(account: account, amount: map(transaction.amount), currency: map(transaction.currency), unparsedUsage: map(transaction.unparsedUsage), bookingDate: map(transaction.bookingDate), otherPartyName: transaction.otherPartyName, otherPartyBankCode: transaction.otherPartyBankCode, otherPartyAccountId: transaction.otherPartyAccountId, bookingText: transaction.bookingText, valueDate: map(transaction.valueDate), statementNumber: Int32(transaction.statementNumber), sequenceNumber: map(transaction.sequenceNumber), openingBalance: map(transaction.openingBalance), closingBalance: map(transaction.closingBalance), endToEndReference: transaction.endToEndReference, customerReference: transaction.customerReference, mandateReference: transaction.mandateReference, creditorIdentifier: transaction.creditorIdentifier, originatorsIdentificationCode: transaction.originatorsIdentificationCode, compensationAmount: transaction.compensationAmount, originalAmount: transaction.originalAmount, sepaUsage: transaction.sepaUsage, deviantOriginator: transaction.deviantOriginator, deviantRecipient: transaction.deviantRecipient, usageWithNoSpecialType: transaction.usageWithNoSpecialType, primaNotaNumber: transaction.primaNotaNumber, textKeySupplement: transaction.textKeySupplement, currencyType: transaction.currencyType, bookingKey: map(transaction.bookingKey), referenceForTheAccountOwner: map(transaction.referenceForTheAccountOwner), referenceOfTheAccountServicingInstitution: transaction.referenceOfTheAccountServicingInstitution, supplementaryDetails: transaction.supplementaryDetails, transactionReferenceNumber: map(transaction.transactionReferenceNumber), relatedReferenceNumber: transaction.relatedReferenceNumber)
|
let mapped = AccountTransaction(account: account, amount: map(transaction.amount), currency: map(transaction.currency), unparsedReference: map(transaction.unparsedReference), bookingDate: map(transaction.bookingDate), otherPartyName: transaction.otherPartyName, otherPartyBankCode: transaction.otherPartyBankCode, otherPartyAccountId: transaction.otherPartyAccountId, bookingText: transaction.bookingText, valueDate: map(transaction.valueDate), statementNumber: Int32(transaction.statementNumber), sequenceNumber: map(transaction.sequenceNumber), openingBalance: map(transaction.openingBalance), closingBalance: map(transaction.closingBalance), endToEndReference: transaction.endToEndReference, customerReference: transaction.customerReference, mandateReference: transaction.mandateReference, creditorIdentifier: transaction.creditorIdentifier, originatorsIdentificationCode: transaction.originatorsIdentificationCode, compensationAmount: transaction.compensationAmount, originalAmount: transaction.originalAmount, sepaReference: transaction.sepaReference, deviantOriginator: transaction.deviantOriginator, deviantRecipient: transaction.deviantRecipient, referenceWithNoSpecialType: transaction.referenceWithNoSpecialType, primaNotaNumber: transaction.primaNotaNumber, textKeySupplement: transaction.textKeySupplement, currencyType: transaction.currencyType, bookingKey: map(transaction.bookingKey), referenceForTheAccountOwner: map(transaction.referenceForTheAccountOwner), referenceOfTheAccountServicingInstitution: transaction.referenceOfTheAccountServicingInstitution, supplementaryDetails: transaction.supplementaryDetails, transactionReferenceNumber: map(transaction.transactionReferenceNumber), relatedReferenceNumber: transaction.relatedReferenceNumber)
|
||||||
|
|
||||||
mapped.technicalId = transaction.objectIDAsString
|
mapped.technicalId = transaction.objectIDAsString
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ class Mapper {
|
||||||
|
|
||||||
mapped.amount = map(transaction.amount)
|
mapped.amount = map(transaction.amount)
|
||||||
mapped.currency = transaction.currency
|
mapped.currency = transaction.currency
|
||||||
mapped.unparsedUsage = transaction.unparsedUsage
|
mapped.unparsedReference = transaction.unparsedReference
|
||||||
mapped.bookingDate = map(transaction.bookingDate)
|
mapped.bookingDate = map(transaction.bookingDate)
|
||||||
mapped.otherPartyName = transaction.otherPartyName
|
mapped.otherPartyName = transaction.otherPartyName
|
||||||
mapped.otherPartyBankCode = transaction.otherPartyBankCode
|
mapped.otherPartyBankCode = transaction.otherPartyBankCode
|
||||||
|
@ -186,10 +186,10 @@ class Mapper {
|
||||||
mapped.originatorsIdentificationCode = transaction.originatorsIdentificationCode
|
mapped.originatorsIdentificationCode = transaction.originatorsIdentificationCode
|
||||||
mapped.compensationAmount = transaction.compensationAmount
|
mapped.compensationAmount = transaction.compensationAmount
|
||||||
mapped.originalAmount = transaction.originalAmount
|
mapped.originalAmount = transaction.originalAmount
|
||||||
mapped.sepaUsage = transaction.sepaUsage
|
mapped.sepaReference = transaction.sepaReference
|
||||||
mapped.deviantOriginator = transaction.deviantOriginator
|
mapped.deviantOriginator = transaction.deviantOriginator
|
||||||
mapped.deviantRecipient = transaction.deviantRecipient
|
mapped.deviantRecipient = transaction.deviantRecipient
|
||||||
mapped.usageWithNoSpecialType = transaction.usageWithNoSpecialType
|
mapped.referenceWithNoSpecialType = transaction.referenceWithNoSpecialType
|
||||||
mapped.primaNotaNumber = transaction.primaNotaNumber
|
mapped.primaNotaNumber = transaction.primaNotaNumber
|
||||||
mapped.textKeySupplement = transaction.textKeySupplement
|
mapped.textKeySupplement = transaction.textKeySupplement
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct BankAccountSettingsDialog: View {
|
||||||
|
|
||||||
CheckmarkListItem("Supports Transferring Money", account.supportsTransferringMoney)
|
CheckmarkListItem("Supports Transferring Money", account.supportsTransferringMoney)
|
||||||
|
|
||||||
CheckmarkListItem("Supports Instant payment transfer", account.supportsInstantPaymentMoneyTransfer)
|
CheckmarkListItem("Supports Real-time transfer", account.supportsRealTimeTransfer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.alert(message: $unsavedChangesMessage)
|
.alert(message: $unsavedChangesMessage)
|
||||||
|
|
|
@ -14,34 +14,34 @@ struct TransferMoneyDialog: View {
|
||||||
|
|
||||||
@State private var selectedAccountIndex = 0
|
@State private var selectedAccountIndex = 0
|
||||||
|
|
||||||
@State private var remitteeName: String = ""
|
@State private var recipientName: String = ""
|
||||||
@State private var isValidRemitteeNameEntered = false
|
@State private var isValidRecipientNameEntered = false
|
||||||
@State private var remitteeNameValidationResult: ValidationResult? = nil
|
@State private var recipientNameValidationResult: ValidationResult? = nil
|
||||||
|
|
||||||
@State private var showRemitteeAutocompleteList = false
|
@State private var showRecipientAutocompleteList = false
|
||||||
@State private var remitteeSearchResults = [Remittee]()
|
@State private var recipientSearchResults = [TransactionParty]()
|
||||||
|
|
||||||
@State private var remitteeIban: String = ""
|
@State private var recipientIban: String = ""
|
||||||
@State private var isValidRemitteeIbanEntered = false
|
@State private var isValidRecipientIbanEntered = false
|
||||||
@State private var remitteeIbanValidationResult: ValidationResult? = nil
|
@State private var recipientIbanValidationResult: ValidationResult? = nil
|
||||||
|
|
||||||
@State private var remitteeBic: String = ""
|
@State private var recipientBic: String = ""
|
||||||
@State private var isValidRemitteeBicEntered = false
|
@State private var isValidRecipientBicEntered = false
|
||||||
@State private var remitteeBicValidationResult: ValidationResult? = nil
|
@State private var recipientBicValidationResult: ValidationResult? = nil
|
||||||
|
|
||||||
@State private var remitteeBankInfo: String? = nil
|
@State private var recipientBankInfo: String? = nil
|
||||||
|
|
||||||
@State private var amount = ""
|
@State private var amount = ""
|
||||||
@State private var isValidAmountEntered = false
|
@State private var isValidAmountEntered = false
|
||||||
@State private var amountValidationResult: ValidationResult? = nil
|
@State private var amountValidationResult: ValidationResult? = nil
|
||||||
|
|
||||||
@State private var usage: String = ""
|
@State private var reference: String = ""
|
||||||
@State private var isValidUsageEntered = true
|
@State private var isValidReferenceEntered = true
|
||||||
@State private var usageValidationResult: ValidationResult? = nil
|
@State private var referenceValidationResult: ValidationResult? = nil
|
||||||
|
|
||||||
@State private var validateDataWhenShowingDialog = false
|
@State private var validateDataWhenShowingDialog = false
|
||||||
|
|
||||||
@State private var instantPayment = false
|
@State private var realTimeTransfer = false
|
||||||
|
|
||||||
@State private var isTransferringMoney = false
|
@State private var isTransferringMoney = false
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ struct TransferMoneyDialog: View {
|
||||||
return self.accountsSupportingTransferringMoney.first
|
return self.accountsSupportingTransferringMoney.first
|
||||||
}
|
}
|
||||||
|
|
||||||
private var supportsInstantPayment: Bool {
|
private var supportsRealTimeTransfer: Bool {
|
||||||
return self.account?.supportsInstantPaymentMoneyTransfer ?? false
|
return self.account?.supportsRealTimeTransfer ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,22 +82,22 @@ struct TransferMoneyDialog: View {
|
||||||
let preselectedBankAccount = preselectedValues.account
|
let preselectedBankAccount = preselectedValues.account
|
||||||
self._selectedAccountIndex = State(initialValue: accountsSupportingTransferringMoney.firstIndex(where: { account in account == preselectedBankAccount }) ?? 0)
|
self._selectedAccountIndex = State(initialValue: accountsSupportingTransferringMoney.firstIndex(where: { account in account == preselectedBankAccount }) ?? 0)
|
||||||
|
|
||||||
self._remitteeName = State(initialValue: preselectedValues.creditorName)
|
self._recipientName = State(initialValue: preselectedValues.recipientName)
|
||||||
self._remitteeBic = State(initialValue: preselectedValues.creditorBic)
|
self._recipientBic = State(initialValue: preselectedValues.recipientBankCode)
|
||||||
self._remitteeIban = State(initialValue: preselectedValues.creditorIban)
|
self._recipientIban = State(initialValue: preselectedValues.recipientAccountId)
|
||||||
|
|
||||||
if remitteeBic.isBlank && remitteeIban.isNotBlank {
|
if recipientBic.isBlank && recipientIban.isNotBlank {
|
||||||
tryToGetBicFromIban(remitteeIban)
|
tryToGetBicFromIban(recipientIban)
|
||||||
}
|
}
|
||||||
|
|
||||||
self._usage = State(initialValue: preselectedValues.usage)
|
self._reference = State(initialValue: preselectedValues.reference)
|
||||||
|
|
||||||
if preselectedValues.amount.decimal != NSDecimalNumber.zero {
|
if preselectedValues.amount.decimal != NSDecimalNumber.zero {
|
||||||
self._amount = State(initialValue: preselectedValues.amount.format(countDecimalPlaces: 2))
|
self._amount = State(initialValue: preselectedValues.amount.format(countDecimalPlaces: 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
if preselectedBankAccount.supportsInstantPaymentMoneyTransfer {
|
if preselectedBankAccount.supportsRealTimeTransfer {
|
||||||
self._instantPayment = State(initialValue: preselectedValues.instantPayment)
|
self._realTimeTransfer = State(initialValue: preselectedValues.realTimeTransfer)
|
||||||
}
|
}
|
||||||
|
|
||||||
_validateDataWhenShowingDialog = State(initialValue: true)
|
_validateDataWhenShowingDialog = State(initialValue: true)
|
||||||
|
@ -117,29 +117,29 @@ struct TransferMoneyDialog: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
LabelledUIKitTextField(label: "Remittee Name", text: $remitteeName, focusOnStart: true, focusNextTextFieldOnReturnKeyPress: true,
|
LabelledUIKitTextField(label: "Recipient Name", text: $recipientName, focusOnStart: true, focusNextTextFieldOnReturnKeyPress: true,
|
||||||
isFocusedChanged: remitteeNameisFocusedChanged, actionOnReturnKeyPress: handleReturnKeyPress, textChanged: enteredRemitteeNameChanged)
|
isFocusedChanged: recipientNameisFocusedChanged, actionOnReturnKeyPress: handleReturnKeyPress, textChanged: enteredRecipientNameChanged)
|
||||||
.padding(.bottom, 0)
|
.padding(.bottom, 0)
|
||||||
|
|
||||||
remitteeNameValidationResult.map { validationError in
|
recipientNameValidationResult.map { validationError in
|
||||||
ValidationLabel(validationError)
|
ValidationLabel(validationError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.showRemitteeAutocompleteList {
|
if self.showRecipientAutocompleteList {
|
||||||
List(self.remitteeSearchResults) { remittee in
|
List(self.recipientSearchResults) { recipient in
|
||||||
RemitteeListItem(remittee: remittee)
|
RecipientListItem(recipient: recipient)
|
||||||
.onTapGesture { self.remitteeSelected(remittee) }
|
.onTapGesture { self.recipientSelected(recipient) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelledUIKitTextField(label: "Remittee IBAN", text: $remitteeIban, autocapitalizationType: .allCharacters, focusNextTextFieldOnReturnKeyPress: true, isFocusedChanged: validateRemitteeIbanOnFocusLost,
|
LabelledUIKitTextField(label: "Recipient IBAN", text: $recipientIban, autocapitalizationType: .allCharacters, focusNextTextFieldOnReturnKeyPress: true, isFocusedChanged: validateRecipientIbanOnFocusLost,
|
||||||
actionOnReturnKeyPress: handleReturnKeyPress, textChanged: remitteeIbanisFocusedChanged)
|
actionOnReturnKeyPress: handleReturnKeyPress, textChanged: recipientIbanisFocusedChanged)
|
||||||
|
|
||||||
remitteeIbanValidationResult.map { validationError in
|
recipientIbanValidationResult.map { validationError in
|
||||||
ValidationLabel(validationError)
|
ValidationLabel(validationError)
|
||||||
}
|
}
|
||||||
|
|
||||||
remitteeBankInfo.map {
|
recipientBankInfo.map {
|
||||||
InfoLabel($0)
|
InfoLabel($0)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}
|
||||||
|
@ -157,29 +157,29 @@ struct TransferMoneyDialog: View {
|
||||||
Section {
|
Section {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Usage")
|
Text("Reference")
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
|
||||||
UIKitTextField("Enter usage", text: $usage, actionOnReturnKeyPress: handleReturnKeyPress, textChanged: validateUsage)
|
UIKitTextField("Enter reference", text: $reference, actionOnReturnKeyPress: handleReturnKeyPress, textChanged: validateReference)
|
||||||
}
|
}
|
||||||
|
|
||||||
usageValidationResult.map { validationError in
|
referenceValidationResult.map { validationError in
|
||||||
ValidationLabel(validationError)
|
ValidationLabel(validationError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if supportsInstantPayment {
|
if supportsRealTimeTransfer {
|
||||||
Section {
|
Section {
|
||||||
VStack {
|
VStack {
|
||||||
Toggle(isOn: $instantPayment) {
|
Toggle(isOn: $realTimeTransfer) {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Instant Payment")
|
Text("Real-time transfer")
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
|
|
||||||
if instantPayment {
|
if realTimeTransfer {
|
||||||
InstantPaymentInfoView()
|
RealTimeTransferInfoView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,8 +205,8 @@ struct TransferMoneyDialog: View {
|
||||||
self.validateDataWhenShowingDialog = false
|
self.validateDataWhenShowingDialog = false
|
||||||
self.validateAllFields()
|
self.validateAllFields()
|
||||||
|
|
||||||
if self.remitteeBankInfo == nil {
|
if self.recipientBankInfo == nil {
|
||||||
self.showRemitteeBankInfo(self.remitteeBic, "")
|
self.showRecipientBankInfo(self.recipientBic, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,104 +228,104 @@ struct TransferMoneyDialog: View {
|
||||||
|
|
||||||
|
|
||||||
private func validateAllFields() {
|
private func validateAllFields() {
|
||||||
self.validateRemitteeNameOnFocusLost()
|
self.validateRecipientNameOnFocusLost()
|
||||||
self.validateRemitteeIbanOnFocusLost()
|
self.validateRecipientIbanOnFocusLost()
|
||||||
self.validateRemitteeBic()
|
self.validateRecipientBic()
|
||||||
self.validateAmount()
|
self.validateAmount()
|
||||||
self.validateUsage()
|
self.validateReference()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func remitteeNameisFocusedChanged(_ isFocused: Bool) {
|
private func recipientNameisFocusedChanged(_ isFocused: Bool) {
|
||||||
if isFocused == false {
|
if isFocused == false {
|
||||||
validateRemitteeNameOnFocusLost()
|
validateRecipientNameOnFocusLost()
|
||||||
|
|
||||||
self.showRemitteeAutocompleteList = false
|
self.showRecipientAutocompleteList = false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.showRemitteeAutocompleteList = self.remitteeSearchResults.isNotEmpty
|
self.showRecipientAutocompleteList = self.recipientSearchResults.isNotEmpty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validateRemitteeNameOnFocusLost() {
|
private func validateRecipientNameOnFocusLost() {
|
||||||
validateField($remitteeName, $remitteeNameValidationResult, $isValidRemitteeNameEntered) {
|
validateField($recipientName, $recipientNameValidationResult, $isValidRecipientNameEntered) {
|
||||||
inputValidator.validateRemitteeName(remitteeNameToTest: remitteeName)
|
inputValidator.validateRecipientName(recipientNameToTest: recipientName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func enteredRemitteeNameChanged(enteredRemitteeName: String) {
|
private func enteredRecipientNameChanged(enteredRecipientName: String) {
|
||||||
validateField($remitteeName, $remitteeNameValidationResult, $isValidRemitteeNameEntered) {
|
validateField($recipientName, $recipientNameValidationResult, $isValidRecipientNameEntered) {
|
||||||
inputValidator.validateRemitteeNameWhileTyping(remitteeNameToTest: remitteeName)
|
inputValidator.validateRecipientNameWhileTyping(recipientNameToTest: recipientName)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchRemittees(remitteeName)
|
searchRecipients(recipientName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func searchRemittees(_ searchText: String) {
|
private func searchRecipients(_ searchText: String) {
|
||||||
// TODO: why doesn't it work to search on background thread?
|
// TODO: why doesn't it work to search on background thread?
|
||||||
self.remitteeSearchResults = self.presenter.findRemitteesForName(name: searchText)
|
self.recipientSearchResults = self.presenter.findRecipientsForName(name: searchText)
|
||||||
|
|
||||||
self.showRemitteeAutocompleteList = self.remitteeSearchResults.isNotEmpty
|
self.showRecipientAutocompleteList = self.recipientSearchResults.isNotEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
private func remitteeSelected(_ remittee: Remittee) {
|
private func recipientSelected(_ recipient: TransactionParty) {
|
||||||
self.remitteeName = remittee.name
|
self.recipientName = recipient.name
|
||||||
self.remitteeIban = remittee.iban ?? self.remitteeIban
|
self.recipientIban = recipient.iban ?? self.recipientIban
|
||||||
self.remitteeBic = remittee.bic ?? self.remitteeBic
|
self.recipientBic = recipient.bic ?? self.recipientBic
|
||||||
|
|
||||||
tryToGetBicFromIban(self.remitteeIban)
|
tryToGetBicFromIban(self.recipientIban)
|
||||||
|
|
||||||
validateAllFields()
|
validateAllFields()
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
|
||||||
self.showRemitteeAutocompleteList = false
|
self.showRecipientAutocompleteList = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func remitteeIbanisFocusedChanged(_ enteredIban: String) {
|
private func recipientIbanisFocusedChanged(_ enteredIban: String) {
|
||||||
validateField($remitteeIban, $remitteeIbanValidationResult, $isValidRemitteeIbanEntered) { inputValidator.validateIbanWhileTyping(ibanToTest: enteredIban) }
|
validateField($recipientIban, $recipientIbanValidationResult, $isValidRecipientIbanEntered) { inputValidator.validateIbanWhileTyping(ibanToTest: enteredIban) }
|
||||||
|
|
||||||
tryToGetBicFromIban(enteredIban)
|
tryToGetBicFromIban(enteredIban)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validateRemitteeIbanOnFocusLost(_ isFocused: Bool) {
|
private func validateRecipientIbanOnFocusLost(_ isFocused: Bool) {
|
||||||
if isFocused == false {
|
if isFocused == false {
|
||||||
validateRemitteeIbanOnFocusLost()
|
validateRecipientIbanOnFocusLost()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validateRemitteeIbanOnFocusLost() {
|
private func validateRecipientIbanOnFocusLost() {
|
||||||
validateField($remitteeIban, $remitteeIbanValidationResult, $isValidRemitteeIbanEntered) { inputValidator.validateIban(ibanToTest: remitteeIban) }
|
validateField($recipientIban, $recipientIbanValidationResult, $isValidRecipientIbanEntered) { inputValidator.validateIban(ibanToTest: recipientIban) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private func tryToGetBicFromIban(_ enteredIban: String) {
|
private func tryToGetBicFromIban(_ enteredIban: String) {
|
||||||
let foundBank = presenter.findUniqueBankForIban(iban: enteredIban)
|
let foundBank = presenter.findUniqueBankForIban(iban: enteredIban)
|
||||||
|
|
||||||
if let foundBank = foundBank {
|
if let foundBank = foundBank {
|
||||||
self.remitteeBic = foundBank.bic
|
self.recipientBic = foundBank.bic
|
||||||
showRemitteeBankInfo(foundBank.bic, foundBank.name)
|
showRecipientBankInfo(foundBank.bic, foundBank.name)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.remitteeBic = ""
|
self.recipientBic = ""
|
||||||
|
|
||||||
if enteredIban.count >= InputValidator.Companion().MinimumLengthToDetermineBicFromIban {
|
if enteredIban.count >= InputValidator.Companion().MinimumLengthToDetermineBicFromIban {
|
||||||
self.remitteeBankInfo = "No BIC found for bank code \(enteredIban[4..<Int(InputValidator.Companion().MinimumLengthToDetermineBicFromIban)])"
|
self.recipientBankInfo = "No BIC found for bank code \(enteredIban[4..<Int(InputValidator.Companion().MinimumLengthToDetermineBicFromIban)])"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.remitteeBankInfo = nil
|
self.recipientBankInfo = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validateRemitteeBic()
|
validateRecipientBic()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validateRemitteeBic() {
|
private func validateRecipientBic() {
|
||||||
self.isValidRemitteeBicEntered = inputValidator.validateBic(bicToTest: remitteeBic).validationSuccessful
|
self.isValidRecipientBicEntered = inputValidator.validateBic(bicToTest: recipientBic).validationSuccessful
|
||||||
}
|
}
|
||||||
|
|
||||||
private func showRemitteeBankInfo(_ bic: String, _ bankName: String) {
|
private func showRecipientBankInfo(_ bic: String, _ bankName: String) {
|
||||||
self.remitteeBankInfo = "BIC: \(bic), \(bankName)"
|
self.recipientBankInfo = "BIC: \(bic), \(bankName)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -352,12 +352,12 @@ struct TransferMoneyDialog: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func validateUsage(enteredUsage: String) {
|
private func validateReference(enteredReference: String) {
|
||||||
validateUsage()
|
validateReference()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validateUsage() {
|
private func validateReference() {
|
||||||
validateField($usage, $usageValidationResult, $isValidUsageEntered) { inputValidator.validateUsage(usageToTest: self.usage) }
|
validateField($reference, $referenceValidationResult, $isValidReferenceEntered) { inputValidator.validateReference(referenceToTest: self.reference) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validateField(_ newValue: Binding<String>, _ validationResult: Binding<ValidationResult?>, _ isValidValueEntered: Binding<Bool>, _ validateValue: () -> ValidationResult) {
|
private func validateField(_ newValue: Binding<String>, _ validationResult: Binding<ValidationResult?>, _ isValidValueEntered: Binding<Bool>, _ validateValue: () -> ValidationResult) {
|
||||||
|
@ -382,11 +382,11 @@ struct TransferMoneyDialog: View {
|
||||||
|
|
||||||
private func isRequiredDataEntered() -> Bool {
|
private func isRequiredDataEntered() -> Bool {
|
||||||
return account != nil
|
return account != nil
|
||||||
&& isValidRemitteeNameEntered
|
&& isValidRecipientNameEntered
|
||||||
&& isValidRemitteeIbanEntered
|
&& isValidRecipientIbanEntered
|
||||||
&& isValidRemitteeBicEntered
|
&& isValidRecipientBicEntered
|
||||||
&& isValidAmountEntered
|
&& isValidAmountEntered
|
||||||
&& isValidUsageEntered
|
&& isValidReferenceEntered
|
||||||
}
|
}
|
||||||
|
|
||||||
private func transferMoney() {
|
private func transferMoney() {
|
||||||
|
@ -394,7 +394,7 @@ struct TransferMoneyDialog: View {
|
||||||
isTransferringMoney = true
|
isTransferringMoney = true
|
||||||
UIApplication.hideKeyboard()
|
UIApplication.hideKeyboard()
|
||||||
|
|
||||||
let data = TransferMoneyData(account: account!, creditorName: remitteeName, creditorIban: remitteeIban, creditorBic: remitteeBic, amount: amount, usage: usage, instantPayment: instantPayment)
|
let data = TransferMoneyData(account: account!, recipientName: recipientName, recipientAccountId: recipientIban, recipientBankCode: recipientBic, amount: amount, reference: reference, realTimeTransfer: realTimeTransfer)
|
||||||
|
|
||||||
presenter.transferMoneyAsync(data: data) { response in
|
presenter.transferMoneyAsync(data: data) { response in
|
||||||
self.handleTransferMoneyResponse(data, response)
|
self.handleTransferMoneyResponse(data, response)
|
||||||
|
@ -406,12 +406,12 @@ struct TransferMoneyDialog: View {
|
||||||
isTransferringMoney = false
|
isTransferringMoney = false
|
||||||
|
|
||||||
if (response.successful) {
|
if (response.successful) {
|
||||||
self.transferMoneyResponseMessage = Message(message: Text("Successfully transferred \(data.amount) \("€") to \(data.creditorName)."), primaryButton: .ok {
|
self.transferMoneyResponseMessage = Message(message: Text("Successfully transferred \(data.amount) \("€") to \(data.recipientName)."), primaryButton: .ok {
|
||||||
self.presentation.wrappedValue.dismiss()
|
self.presentation.wrappedValue.dismiss()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else if response.userCancelledAction == false {
|
else if response.userCancelledAction == false {
|
||||||
self.transferMoneyResponseMessage = Message(message: Text("Could not transfer \(data.amount) \("€") to \(data.creditorName). Error: \(response.errorToShowToUser ?? "")."))
|
self.transferMoneyResponseMessage = Message(message: Text("Could not transfer \(data.amount) \("€") to \(data.recipientName). Error: \(response.errorToShowToUser ?? "")."))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
struct InstantPaymentInfoView: View {
|
struct RealTimeTransferInfoView: View {
|
||||||
|
|
||||||
@State private var showInstantPaymentInfoPopover = false
|
@State private var showRealTimeTransferInfoPopover = false
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -15,26 +15,26 @@ struct InstantPaymentInfoView: View {
|
||||||
.minimumScaleFactor(0.5)
|
.minimumScaleFactor(0.5)
|
||||||
.padding(.horizontal, 0)
|
.padding(.horizontal, 0)
|
||||||
|
|
||||||
UIKitButton(.infoLight) { self.showInstantPaymentInfoPopover = true }
|
UIKitButton(.infoLight) { self.showRealTimeTransferInfoPopover = true }
|
||||||
.frame(width: 15, height: 15)
|
.frame(width: 15, height: 15)
|
||||||
.popover(isPresented: $showInstantPaymentInfoPopover, arrowEdge: .leading ) {
|
.popover(isPresented: $showRealTimeTransferInfoPopover, arrowEdge: .leading ) {
|
||||||
if UIDevice.isRunningOniPad {
|
if UIDevice.isRunningOniPad {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
Text("Instant payment information")
|
Text("Real-time transfer information")
|
||||||
.padding()
|
.padding()
|
||||||
.detailForegroundColor()
|
.detailForegroundColor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VStack {
|
VStack {
|
||||||
Text("Instant payment information")
|
Text("Real-time transfer information")
|
||||||
.padding()
|
.padding()
|
||||||
.detailForegroundColor()
|
.detailForegroundColor()
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Button("OK") { self.showInstantPaymentInfoPopover = false }
|
Button("OK") { self.showRealTimeTransferInfoPopover = false }
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
@ -47,13 +47,13 @@ struct InstantPaymentInfoView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct InstantPaymentInfoView_Previews: PreviewProvider {
|
struct RealTimeTransferInfoView_Previews: PreviewProvider {
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Form {
|
Form {
|
||||||
Section {
|
Section {
|
||||||
Toggle(isOn: .constant(true)) {
|
Toggle(isOn: .constant(true)) {
|
||||||
InstantPaymentInfoView()
|
RealTimeTransferInfoView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -36,7 +36,7 @@ struct AccountTransactionListItem: View {
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.frame(height: 20)
|
.frame(height: 20)
|
||||||
|
|
||||||
Text(transaction.usage)
|
Text(transaction.reference)
|
||||||
.styleAsDetail()
|
.styleAsDetail()
|
||||||
.padding(.top, 4)
|
.padding(.top, 4)
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
|
@ -62,7 +62,7 @@ struct AccountTransactionListItem: View {
|
||||||
}
|
}
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
if transaction.canCreateMoneyTransferFrom {
|
if transaction.canCreateMoneyTransferFrom {
|
||||||
NavigationLink(destination: LazyView(TransferMoneyDialog(preselectedValues: TransferMoneyData.Companion().fromAccountTransactionWithoutAmountAndUsage(transaction: self.transaction)))) {
|
NavigationLink(destination: LazyView(TransferMoneyDialog(preselectedValues: TransferMoneyData.Companion().fromAccountTransactionWithoutAmountAndReference(transaction: self.transaction)))) {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Transfer money to \(transaction.otherPartyName ?? "")")
|
Text("Transfer money to \(transaction.otherPartyName ?? "")")
|
||||||
|
|
||||||
|
@ -98,6 +98,6 @@ struct AccountTransactionListItem: View {
|
||||||
|
|
||||||
struct AccountTransactionListItem_Previews: PreviewProvider {
|
struct AccountTransactionListItem_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
AccountTransactionListItem(AccountTransaction(account: previewBanks[0].accounts[0] as! BankAccount, otherPartyName: "Marieke Musterfrau", unparsedUsage: "Vielen Dank für Ihre Mühen", amount: CommonBigDecimal(double: 1234.56), valueDate: CommonDate(year: 2020, month: .march, day_: 27), bookingText: "SEPA Überweisung"), false)
|
AccountTransactionListItem(AccountTransaction(account: previewBanks[0].accounts[0] as! BankAccount, otherPartyName: "Marieke Musterfrau", unparsedReference: "Vielen Dank für Ihre Mühen", amount: CommonBigDecimal(double: 1234.56), valueDate: CommonDate(year: 2020, month: .march, day_: 27), bookingText: "SEPA Überweisung"), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,16 @@ import SwiftUI
|
||||||
import BankingUiSwift
|
import BankingUiSwift
|
||||||
|
|
||||||
|
|
||||||
struct RemitteeListItem: View {
|
struct RecipientListItem: View {
|
||||||
|
|
||||||
let remittee: Remittee
|
let recipient: TransactionParty
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Text(remittee.name)
|
Text(recipient.name)
|
||||||
.bold()
|
.bold()
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ struct RemitteeListItem: View {
|
||||||
}
|
}
|
||||||
.padding(.vertical, 6)
|
.padding(.vertical, 6)
|
||||||
|
|
||||||
remittee.bankName.map { bankName in
|
recipient.bankName.map { bankName in
|
||||||
HStack {
|
HStack {
|
||||||
Text(bankName)
|
Text(bankName)
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
|
@ -31,11 +31,11 @@ struct RemitteeListItem: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Text(remittee.iban ?? "")
|
Text(recipient.iban ?? "")
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Text(remittee.bic ?? "")
|
Text(recipient.bic ?? "")
|
||||||
}
|
}
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
|
@ -45,10 +45,10 @@ struct RemitteeListItem: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RemitteeListItem_Previews: PreviewProvider {
|
struct RecipientListItem_Previews: PreviewProvider {
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
RemitteeListItem(remittee: Remittee(name: "Marieke Musterfrau", iban: "DE12876543211234567890", bic: "ABZODEBBXX", bankName: "Abzockbank Berlin"))
|
RecipientListItem(recipient: TransactionParty(name: "Marieke Musterfrau", iban: "DE12876543211234567890", bic: "ABZODEBBXX", bankName: "Abzockbank Berlin"))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -117,7 +117,7 @@ open class fints4kBankingClient(
|
||||||
callback(BankingClientResponse(false, errorMessage))
|
callback(BankingClientResponse(false, errorMessage))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val mappedData = BankTransferData(data.creditorName, data.creditorIban, data.creditorBic, data.amount.toMoney(), data.usage, data.instantPayment)
|
val mappedData = BankTransferData(data.recipientName, data.recipientAccountId, data.recipientBankCode, data.amount.toMoney(), data.reference, data.realTimeTransfer)
|
||||||
|
|
||||||
doBankTransferAsync(mappedData, account, callback)
|
doBankTransferAsync(mappedData, account, callback)
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ open class fints4kModelMapper(protected val modelCreator: IModelCreator) {
|
||||||
account.supportsRetrievingBalance = accountData.supportsRetrievingBalance
|
account.supportsRetrievingBalance = accountData.supportsRetrievingBalance
|
||||||
account.supportsRetrievingAccountTransactions = accountData.supportsRetrievingAccountTransactions
|
account.supportsRetrievingAccountTransactions = accountData.supportsRetrievingAccountTransactions
|
||||||
account.supportsTransferringMoney = accountData.supportsTransferringMoney
|
account.supportsTransferringMoney = accountData.supportsTransferringMoney
|
||||||
account.supportsInstantPaymentMoneyTransfer = accountData.supportsInstantPaymentMoneyTransfer
|
account.supportsRealTimeTransfer = accountData.supportsRealTimeTransfer
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun mapBankAccountType(type: AccountType?): BankAccountType {
|
open fun mapBankAccountType(type: AccountType?): BankAccountType {
|
||||||
|
@ -199,7 +199,7 @@ open class fints4kModelMapper(protected val modelCreator: IModelCreator) {
|
||||||
account,
|
account,
|
||||||
transaction.amount.bigDecimal,
|
transaction.amount.bigDecimal,
|
||||||
transaction.amount.currency.code,
|
transaction.amount.currency.code,
|
||||||
transaction.unparsedUsage,
|
transaction.unparsedReference,
|
||||||
transaction.bookingDate,
|
transaction.bookingDate,
|
||||||
transaction.otherPartyName,
|
transaction.otherPartyName,
|
||||||
transaction.otherPartyBankCode,
|
transaction.otherPartyBankCode,
|
||||||
|
@ -218,10 +218,10 @@ open class fints4kModelMapper(protected val modelCreator: IModelCreator) {
|
||||||
transaction.originatorsIdentificationCode,
|
transaction.originatorsIdentificationCode,
|
||||||
transaction.compensationAmount,
|
transaction.compensationAmount,
|
||||||
transaction.originalAmount,
|
transaction.originalAmount,
|
||||||
transaction.sepaUsage,
|
transaction.sepaReference,
|
||||||
transaction.deviantOriginator,
|
transaction.deviantOriginator,
|
||||||
transaction.deviantRecipient,
|
transaction.deviantRecipient,
|
||||||
transaction.usageWithNoSpecialType,
|
transaction.referenceWithNoSpecialType,
|
||||||
transaction.primaNotaNumber,
|
transaction.primaNotaNumber,
|
||||||
transaction.textKeySupplement,
|
transaction.textKeySupplement,
|
||||||
|
|
||||||
|
|
|
@ -256,7 +256,7 @@ open class hbci4jBankingClient(
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun createTransferCashJob(handle: HBCIHandler, data: TransferMoneyData) {
|
protected open fun createTransferCashJob(handle: HBCIHandler, data: TransferMoneyData) {
|
||||||
// TODO: implement instant payment
|
// TODO: implement real-time transfer
|
||||||
val transferCashJob = handle.newJob("UebSEPA")
|
val transferCashJob = handle.newJob("UebSEPA")
|
||||||
|
|
||||||
val source = mapper.mapToKonto(data.account)
|
val source = mapper.mapToKonto(data.account)
|
||||||
|
@ -266,7 +266,7 @@ open class hbci4jBankingClient(
|
||||||
transferCashJob.setParam("src", source)
|
transferCashJob.setParam("src", source)
|
||||||
transferCashJob.setParam("dst", destination)
|
transferCashJob.setParam("dst", destination)
|
||||||
transferCashJob.setParam("btg", amount)
|
transferCashJob.setParam("btg", amount)
|
||||||
transferCashJob.setParam("usage", data.usage)
|
transferCashJob.setParam("usage", data.reference)
|
||||||
|
|
||||||
transferCashJob.addToQueue()
|
transferCashJob.addToQueue()
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,12 @@ open class AccountTransactionMapper(
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun mapTransaction(account: TypedBankAccount, btag: GVRKUms.BTag, transaction: GVRKUms.UmsLine): IAccountTransaction {
|
protected open fun mapTransaction(account: TypedBankAccount, btag: GVRKUms.BTag, transaction: GVRKUms.UmsLine): IAccountTransaction {
|
||||||
val unparsedUsage = transaction.usage.joinToString("")
|
val unparsedReference = transaction.usage.joinToString("")
|
||||||
val parsedUsage = Mt940Parser().getUsageParts(unparsedUsage)
|
val parsedReference = Mt940Parser().getReferenceParts(unparsedReference)
|
||||||
val statementAndMaySequenceNumber = btag.counter.split('/')
|
val statementAndMaySequenceNumber = btag.counter.split('/')
|
||||||
|
|
||||||
return modelCreator.createTransaction(account,
|
return modelCreator.createTransaction(account,
|
||||||
mapValue(transaction.value), transaction.value.curr, unparsedUsage, transaction.bdate.toDate(),
|
mapValue(transaction.value), transaction.value.curr, unparsedReference, transaction.bdate.toDate(),
|
||||||
transaction.other.name + (transaction.other.name2 ?: ""),
|
transaction.other.name + (transaction.other.name2 ?: ""),
|
||||||
transaction.other.bic ?: transaction.other.blz,
|
transaction.other.bic ?: transaction.other.blz,
|
||||||
transaction.other.iban ?: transaction.other.number,
|
transaction.other.iban ?: transaction.other.number,
|
||||||
|
@ -57,17 +57,17 @@ open class AccountTransactionMapper(
|
||||||
if (statementAndMaySequenceNumber.size > 1) statementAndMaySequenceNumber[1].toInt() else null,
|
if (statementAndMaySequenceNumber.size > 1) statementAndMaySequenceNumber[1].toInt() else null,
|
||||||
mapValue(btag.start.value), mapValue(btag.end.value),
|
mapValue(btag.start.value), mapValue(btag.end.value),
|
||||||
|
|
||||||
parsedUsage[Mt940Parser.EndToEndReferenceUsageKey],
|
parsedReference[Mt940Parser.EndToEndReferenceKey],
|
||||||
parsedUsage[Mt940Parser.CustomerReferenceUsageKey],
|
parsedReference[Mt940Parser.CustomerReferenceKey],
|
||||||
parsedUsage[Mt940Parser.MandateReferenceUsageKey],
|
parsedReference[Mt940Parser.MandateReferenceKey],
|
||||||
parsedUsage[Mt940Parser.CreditorIdentifierUsageKey],
|
parsedReference[Mt940Parser.CreditorIdentifierKey],
|
||||||
parsedUsage[Mt940Parser.OriginatorsIdentificationCodeUsageKey],
|
parsedReference[Mt940Parser.OriginatorsIdentificationCodeKey],
|
||||||
parsedUsage[Mt940Parser.CompensationAmountUsageKey],
|
parsedReference[Mt940Parser.CompensationAmountKey],
|
||||||
parsedUsage[Mt940Parser.OriginalAmountUsageKey],
|
parsedReference[Mt940Parser.OriginalAmountKey],
|
||||||
parsedUsage[Mt940Parser.SepaUsageUsageKey],
|
parsedReference[Mt940Parser.SepaReferenceKey],
|
||||||
parsedUsage[Mt940Parser.DeviantOriginatorUsageKey],
|
parsedReference[Mt940Parser.DeviantOriginatorKey],
|
||||||
parsedUsage[Mt940Parser.DeviantRecipientUsageKey],
|
parsedReference[Mt940Parser.DeviantRecipientKey],
|
||||||
parsedUsage[""],
|
parsedReference[""],
|
||||||
transaction.primanota,
|
transaction.primanota,
|
||||||
transaction.addkey,
|
transaction.addkey,
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ open class hbci4jModelMapper(
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun mapToKonto(data: TransferMoneyData): Konto {
|
open fun mapToKonto(data: TransferMoneyData): Konto {
|
||||||
return mapToKonto(data.creditorName, data.creditorIban, data.creditorBic)
|
return mapToKonto(data.recipientName, data.recipientAccountId, data.recipientBankCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun mapToKonto(accountHolderName: String, iban: String, bic: String): Konto {
|
open fun mapToKonto(accountHolderName: String, iban: String, bic: String): Konto {
|
||||||
|
|
Loading…
Reference in New Issue