Implemented that for retrieving account transactions and for bank transfer the concrete AccountData is required (as for CustomerData with multiple accounts using CustomerData will not work)
This commit is contained in:
parent
0c92a25d92
commit
57aba0971d
|
@ -18,6 +18,6 @@ interface IBankingClient {
|
|||
callback: (GetTransactionsResponse) -> Unit
|
||||
)
|
||||
|
||||
fun transferMoneyAsync(data: TransferMoneyData, callback: (BankingClientResponse) -> Unit)
|
||||
fun transferMoneyAsync(data: TransferMoneyData, bankAccount: BankAccount, callback: (BankingClientResponse) -> Unit)
|
||||
|
||||
}
|
|
@ -220,7 +220,7 @@ open class MainWindowPresenter(
|
|||
|
||||
open fun transferMoneyAsync(bankAccount: BankAccount, data: TransferMoneyData, callback: (BankingClientResponse) -> Unit) {
|
||||
getClientForAccount(bankAccount.account)?.let { client ->
|
||||
client.transferMoneyAsync(data, callback)
|
||||
client.transferMoneyAsync(data, bankAccount, callback)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,20 +79,34 @@ open class fints4javaBankingClient(
|
|||
}
|
||||
|
||||
override fun getTransactionsAsync(bankAccount: BankAccount, parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
client.getTransactionsAsync(net.dankito.fints.model.GetTransactionsParameter(parameter.alsoRetrieveBalance, parameter.fromDate, parameter.toDate)) { response ->
|
||||
val account = mapper.findAccountForBankAccount(customer, bankAccount)
|
||||
|
||||
if (account == null) {
|
||||
callback(GetTransactionsResponse(false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate
|
||||
}
|
||||
else {
|
||||
client.getTransactionsAsync(net.dankito.fints.model.GetTransactionsParameter(parameter.alsoRetrieveBalance, parameter.fromDate, parameter.toDate), account) { response ->
|
||||
|
||||
val mappedResponse = mapper.mapResponse(bankAccount, response)
|
||||
|
||||
callback(mappedResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transferMoneyAsync(data: TransferMoneyData, callback: (BankingClientResponse) -> Unit) {
|
||||
override fun transferMoneyAsync(data: TransferMoneyData, bankAccount: BankAccount, callback: (BankingClientResponse) -> Unit) {
|
||||
val account = mapper.findAccountForBankAccount(customer, bankAccount)
|
||||
|
||||
if (account == null) {
|
||||
callback(BankingClientResponse(false, "Cannot find account for ${bankAccount.identifier}")) // TODO: translate
|
||||
}
|
||||
else {
|
||||
val mappedData = BankTransferData(data.creditorName, data.creditorIban, data.creditorBic, data.amount, data.usage)
|
||||
|
||||
client.doBankTransferAsync(mappedData) { response ->
|
||||
client.doBankTransferAsync(mappedData, account) { response ->
|
||||
callback(mapper.mapResponse(response))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -91,6 +91,11 @@ open class fints4javaModelMapper {
|
|||
}
|
||||
}
|
||||
|
||||
open fun findAccountForBankAccount(customer: CustomerData, bankAccount: BankAccount): AccountData? {
|
||||
return customer.accounts.firstOrNull { bankAccount.identifier == it.accountIdentifier }
|
||||
}
|
||||
|
||||
|
||||
open fun mapTransactions(bankAccount: BankAccount, transactions: List<net.dankito.fints.model.AccountTransaction>): List<AccountTransaction> {
|
||||
return transactions.map { mapTransaction(bankAccount, it) }
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherhe
|
|||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.fints.model.*
|
||||
import net.dankito.fints.response.InstituteSegmentId
|
||||
import net.dankito.fints.response.Response
|
||||
|
@ -152,7 +153,8 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
getTanMediaList(bank, customer, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien)
|
||||
|
||||
// also check if retrieving account transactions of last 90 days without tan is supported (and thereby may retrieve first account transactions)
|
||||
val transactionsOfLast90DaysResponse = tryGetTransactionsOfLast90DaysWithoutTan(bank, customer, false)
|
||||
val account = getBestAccountForRetrievingTransactions(customer)
|
||||
val transactionsOfLast90DaysResponse = if (account != null) tryGetTransactionsOfLast90DaysWithoutTan(bank, customer, account, false) else GetTransactionsResponse(Response(false))
|
||||
|
||||
if (didOverwriteUserUnselectedTanProcedure) {
|
||||
customer.resetSelectedTanProcedure()
|
||||
|
@ -172,12 +174,12 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
*
|
||||
* Check if bank supports this.
|
||||
*/
|
||||
open fun tryGetTransactionsOfLast90DaysWithoutTan(bank: BankData, customer: CustomerData,
|
||||
open fun tryGetTransactionsOfLast90DaysWithoutTan(bank: BankData, customer: CustomerData, account: AccountData,
|
||||
hasRetrievedTransactionsWithTanJustBefore: Boolean): GetTransactionsResponse {
|
||||
|
||||
val ninetyDaysAgo = Date(Date().time - NinetyDaysAgoMilliseconds)
|
||||
|
||||
val response = getTransactions(GetTransactionsParameter(true, ninetyDaysAgo), bank, customer)
|
||||
val response = getTransactions(GetTransactionsParameter(true, ninetyDaysAgo), bank, customer, account)
|
||||
|
||||
|
||||
customer.triedToRetrieveTransactionsOfLast90DaysWithoutTan = true
|
||||
|
@ -192,15 +194,15 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
open fun getTransactionsAsync(parameter: GetTransactionsParameter, bank: BankData,
|
||||
customer: CustomerData, callback: (GetTransactionsResponse) -> Unit) {
|
||||
customer: CustomerData, account: AccountData, callback: (GetTransactionsResponse) -> Unit) {
|
||||
|
||||
threadPool.runAsync {
|
||||
callback(getTransactions(parameter, bank, customer))
|
||||
callback(getTransactions(parameter, bank, customer, account))
|
||||
}
|
||||
}
|
||||
|
||||
open fun getTransactions(parameter: GetTransactionsParameter, bank: BankData,
|
||||
customer: CustomerData): GetTransactionsResponse {
|
||||
customer: CustomerData, account: AccountData): GetTransactionsResponse {
|
||||
|
||||
val dialogData = DialogData()
|
||||
|
||||
|
@ -214,7 +216,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
var balance: BigDecimal? = null
|
||||
|
||||
if (parameter.alsoRetrieveBalance) {
|
||||
val balanceResponse = getBalanceAfterDialogInit(bank, customer, dialogData)
|
||||
val balanceResponse = getBalanceAfterDialogInit(bank, customer, account, dialogData)
|
||||
|
||||
if (balanceResponse.successful == false && balanceResponse.couldCreateMessage == true) { // don't break here if required HKSAL message is not implemented
|
||||
closeDialog(bank, customer, dialogData)
|
||||
|
@ -231,7 +233,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
|
||||
val message = messageBuilder.createGetTransactionsMessage(parameter, bank, customer, product, dialogData)
|
||||
val message = messageBuilder.createGetTransactionsMessage(parameter, bank, customer, account, product, dialogData)
|
||||
|
||||
val response = getAndHandleResponseForMessageThatMayRequiresTan(message, bank, customer, dialogData)
|
||||
|
||||
|
@ -242,7 +244,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
// just retrieved all transactions -> check if retrieving that ones of last 90 days is possible without entering TAN
|
||||
if (customer.supportsRetrievingTransactionsOfLast90DaysWithoutTan == null &&
|
||||
response.successful && transactions.bookedTransactionsString.isNotEmpty() && parameter.fromDate == null) {
|
||||
tryGetTransactionsOfLast90DaysWithoutTan(bank, customer, true)
|
||||
tryGetTransactionsOfLast90DaysWithoutTan(bank, customer, account, true)
|
||||
}
|
||||
|
||||
val bookedAndUnbookedTransactions = getTransactionsFromResponse(response, transactions)
|
||||
|
@ -284,12 +286,12 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
protected open fun getBalanceAfterDialogInit(bank: BankData, customer: CustomerData,
|
||||
protected open fun getBalanceAfterDialogInit(bank: BankData, customer: CustomerData, account: AccountData,
|
||||
dialogData: DialogData): Response {
|
||||
|
||||
dialogData.increaseMessageNumber()
|
||||
|
||||
val balanceRequest = messageBuilder.createGetBalanceMessage(bank, customer, product, dialogData)
|
||||
val balanceRequest = messageBuilder.createGetBalanceMessage(bank, customer, account, product, dialogData)
|
||||
|
||||
return getAndHandleResponseForMessage(balanceRequest, bank)
|
||||
}
|
||||
|
@ -373,15 +375,15 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
|
||||
|
||||
open fun doBankTransferAsync(bankTransferData: BankTransferData, bank: BankData,
|
||||
customer: CustomerData, callback: (FinTsClientResponse) -> Unit) {
|
||||
customer: CustomerData, account: AccountData, callback: (FinTsClientResponse) -> Unit) {
|
||||
|
||||
threadPool.runAsync {
|
||||
callback(doBankTransfer(bankTransferData, bank, customer))
|
||||
callback(doBankTransfer(bankTransferData, bank, customer, account))
|
||||
}
|
||||
}
|
||||
|
||||
open fun doBankTransfer(bankTransferData: BankTransferData, bank: BankData,
|
||||
customer: CustomerData): FinTsClientResponse {
|
||||
customer: CustomerData, account: AccountData): FinTsClientResponse {
|
||||
|
||||
val dialogData = DialogData()
|
||||
|
||||
|
@ -394,7 +396,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
|
||||
dialogData.increaseMessageNumber()
|
||||
|
||||
val message = messageBuilder.createBankTransferMessage(bankTransferData, bank, customer, dialogData)
|
||||
val message = messageBuilder.createBankTransferMessage(bankTransferData, bank, customer, account, dialogData)
|
||||
|
||||
val response = getAndHandleResponseForMessageThatMayRequiresTan(message, bank, customer, dialogData)
|
||||
|
||||
|
@ -791,10 +793,6 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
response.getSegmentsById<AccountInfo>(InstituteSegmentId.AccountInfo).forEach { accountInfo ->
|
||||
if (customer.iban == null && accountInfo.iban != null) {
|
||||
customer.iban = accountInfo.iban // TODO: remove and use that one from AccountData
|
||||
}
|
||||
|
||||
var accountHolderName = accountInfo.accountHolderName1
|
||||
accountInfo.accountHolderName2?.let {
|
||||
accountHolderName += it // TODO: add a whitespace in between?
|
||||
|
@ -817,9 +815,9 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
response.getFirstSegmentById<SepaAccountInfo>(InstituteSegmentId.SepaAccountInfo)?.let { sepaAccountInfo ->
|
||||
// TODO: may also make use of other info
|
||||
// TODO: make use of information
|
||||
sepaAccountInfo.account.iban?.let {
|
||||
customer.iban = it
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -837,7 +835,7 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
|
||||
response.getFirstSegmentById<CommunicationInfo>(InstituteSegmentId.CommunicationInfo)?.let { communicationInfo ->
|
||||
if (customer.selectedLanguage != communicationInfo.defaultLanguage) {
|
||||
customer.selectedLanguage == communicationInfo.defaultLanguage
|
||||
customer.selectedLanguage = communicationInfo.defaultLanguage
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -940,4 +938,9 @@ open class FinTsClient @JvmOverloads constructor(
|
|||
return null
|
||||
}
|
||||
|
||||
|
||||
internal fun getBestAccountForRetrievingTransactions(customer: CustomerData): AccountData? {
|
||||
return customer.accounts.firstOrNull { it.allowedJobNames.contains(CustomerSegmentId.AccountTransactionsMt940.id) }
|
||||
}
|
||||
|
||||
}
|
|
@ -35,12 +35,12 @@ open class FinTsClientForCustomer(
|
|||
client.addAccountAsync(bank, customer, callback)
|
||||
}
|
||||
|
||||
open fun getTransactionsAsync(parameter: GetTransactionsParameter, callback: (GetTransactionsResponse) -> Unit) {
|
||||
client.getTransactionsAsync(parameter, bank, customer, callback)
|
||||
open fun getTransactionsAsync(parameter: GetTransactionsParameter, account: AccountData, callback: (GetTransactionsResponse) -> Unit) {
|
||||
client.getTransactionsAsync(parameter, bank, customer, account, callback)
|
||||
}
|
||||
|
||||
open fun doBankTransferAsync(bankTransferData: BankTransferData, callback: (FinTsClientResponse) -> Unit) {
|
||||
client.doBankTransferAsync(bankTransferData, bank, customer, callback)
|
||||
open fun doBankTransferAsync(bankTransferData: BankTransferData, account: AccountData, callback: (FinTsClientResponse) -> Unit) {
|
||||
client.doBankTransferAsync(bankTransferData, bank, customer, account, callback)
|
||||
}
|
||||
|
||||
}
|
|
@ -108,14 +108,14 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
|
||||
|
||||
open fun createGetTransactionsMessage(parameter: GetTransactionsParameter, bank: BankData, customer: CustomerData,
|
||||
product: ProductData, dialogData: DialogData): MessageBuilderResult {
|
||||
account: AccountData, product: ProductData, dialogData: DialogData): MessageBuilderResult {
|
||||
|
||||
val result = getSupportedVersionsOfJob(CustomerSegmentId.AccountTransactionsMt940, customer, listOf(5, 6, 7))
|
||||
val result = getSupportedVersionsOfJob(CustomerSegmentId.AccountTransactionsMt940, account, listOf(5, 6, 7))
|
||||
|
||||
if (result.isJobVersionSupported) {
|
||||
val transactionsJob = if (result.isAllowed(7)) KontoumsaetzeZeitraumMt940Version7(generator.resetSegmentNumber(2), parameter, bank, customer)
|
||||
else if (result.isAllowed(6)) KontoumsaetzeZeitraumMt940Version6(generator.resetSegmentNumber(2), parameter, bank, customer)
|
||||
else KontoumsaetzeZeitraumMt940Version5(generator.resetSegmentNumber(2), parameter, bank, customer)
|
||||
val transactionsJob = if (result.isAllowed(7)) KontoumsaetzeZeitraumMt940Version7(generator.resetSegmentNumber(2), parameter, bank, account)
|
||||
else if (result.isAllowed(6)) KontoumsaetzeZeitraumMt940Version6(generator.resetSegmentNumber(2), parameter, account)
|
||||
else KontoumsaetzeZeitraumMt940Version5(generator.resetSegmentNumber(2), parameter, account)
|
||||
|
||||
val segments = listOf(
|
||||
transactionsJob,
|
||||
|
@ -128,13 +128,13 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
return result
|
||||
}
|
||||
|
||||
open fun createGetBalanceMessage(bank: BankData, customer: CustomerData, product: ProductData, dialogData: DialogData): MessageBuilderResult {
|
||||
open fun createGetBalanceMessage(bank: BankData, customer: CustomerData, account: AccountData, product: ProductData, dialogData: DialogData): MessageBuilderResult {
|
||||
|
||||
val result = getSupportedVersionsOfJob(CustomerSegmentId.Balance, customer, listOf(5))
|
||||
val result = getSupportedVersionsOfJob(CustomerSegmentId.Balance, account, listOf(5))
|
||||
|
||||
if (result.isJobVersionSupported) {
|
||||
val segments = listOf(
|
||||
Saldenabfrage(generator.resetSegmentNumber(2), bank, customer),
|
||||
Saldenabfrage(generator.resetSegmentNumber(2), account),
|
||||
ZweiSchrittTanEinreichung(generator.getNextSegmentNumber(), TanProcess.TanProcess4, CustomerSegmentId.Balance)
|
||||
)
|
||||
|
||||
|
@ -191,15 +191,15 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
}
|
||||
|
||||
|
||||
open fun createBankTransferMessage(bankTransferData: BankTransferData, bank: BankData, customer: CustomerData, dialogData: DialogData): MessageBuilderResult {
|
||||
open fun createBankTransferMessage(bankTransferData: BankTransferData, bank: BankData, customer: CustomerData, account: AccountData, dialogData: DialogData): MessageBuilderResult {
|
||||
|
||||
val result = getSupportedVersionsOfJob(CustomerSegmentId.SepaBankTransfer, customer, listOf(1))
|
||||
val result = getSupportedVersionsOfJob(CustomerSegmentId.SepaBankTransfer, account, listOf(1))
|
||||
|
||||
if (result.isJobVersionSupported) {
|
||||
|
||||
getSepaUrnFor(CustomerSegmentId.SepaAccountInfoParameters, customer, "pain.001.001.03")?.let { urn ->
|
||||
getSepaUrnFor(CustomerSegmentId.SepaAccountInfoParameters, account, "pain.001.001.03")?.let { urn ->
|
||||
val segments = listOf(
|
||||
SepaEinzelueberweisung(generator.resetSegmentNumber(2), urn, customer, bank.bic, bankTransferData),
|
||||
SepaEinzelueberweisung(generator.resetSegmentNumber(2), urn, customer, account, bank.bic, bankTransferData),
|
||||
ZweiSchrittTanEinreichung(generator.getNextSegmentNumber(), TanProcess.TanProcess4, CustomerSegmentId.SepaBankTransfer)
|
||||
)
|
||||
|
||||
|
@ -326,39 +326,58 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
|||
}
|
||||
|
||||
|
||||
protected open fun getSupportedVersionsOfJob(segmentId: CustomerSegmentId, account: AccountData,
|
||||
supportedVersions: List<Int>): MessageBuilderResult {
|
||||
|
||||
val allowedJobs = getAllowedJobs(segmentId, account)
|
||||
|
||||
return getSupportedVersionsOfJob(supportedVersions, allowedJobs)
|
||||
}
|
||||
|
||||
// TODO: try to get rid of
|
||||
protected open fun getSupportedVersionsOfJob(segmentId: CustomerSegmentId, customer: CustomerData,
|
||||
supportedVersions: List<Int>): MessageBuilderResult {
|
||||
|
||||
val allowedJobs = getAllowedJobs(segmentId, customer)
|
||||
|
||||
return getSupportedVersionsOfJob(supportedVersions, allowedJobs)
|
||||
}
|
||||
|
||||
protected open fun getSupportedVersionsOfJob(supportedVersions: List<Int>, allowedJobs: List<JobParameters>): MessageBuilderResult {
|
||||
if (allowedJobs.isNotEmpty()) {
|
||||
val allowedVersions = allowedJobs
|
||||
.map { it.segmentVersion }
|
||||
.sortedDescending()
|
||||
|
||||
return MessageBuilderResult(allowedVersions.isNotEmpty(), allowedVersions.containsAny(supportedVersions),
|
||||
allowedVersions, supportedVersions, null)
|
||||
return MessageBuilderResult(
|
||||
allowedVersions.isNotEmpty(), allowedVersions.containsAny(supportedVersions),
|
||||
allowedVersions, supportedVersions, null
|
||||
)
|
||||
}
|
||||
|
||||
return MessageBuilderResult(false)
|
||||
}
|
||||
|
||||
protected open fun getSepaUrnFor(segmentId: CustomerSegmentId, customer: CustomerData, sepaDataFormat: String): String? {
|
||||
protected open fun getSepaUrnFor(segmentId: CustomerSegmentId, account: AccountData, sepaDataFormat: String): String? {
|
||||
|
||||
return getAllowedJobs(segmentId, customer)
|
||||
return getAllowedJobs(segmentId, account)
|
||||
.filterIsInstance<SepaAccountInfoParameters>()
|
||||
.sortedByDescending { it.segmentVersion }
|
||||
.flatMap { it.supportedSepaFormats }
|
||||
.firstOrNull { it.contains(sepaDataFormat) }
|
||||
}
|
||||
|
||||
protected open fun getAllowedJobs(segmentId: CustomerSegmentId, customer: CustomerData): List<JobParameters> {
|
||||
protected open fun getAllowedJobs(segmentId: CustomerSegmentId, account: AccountData): List<JobParameters> {
|
||||
|
||||
customer.accounts.firstOrNull()?.let { account -> // TODO: find a better solution / make more generic
|
||||
return account.allowedJobs.filter { it.jobName == segmentId.id }
|
||||
}
|
||||
|
||||
return listOf()
|
||||
// TODO: this implementation is in most cases wrong, try to get rid of
|
||||
protected open fun getAllowedJobs(segmentId: CustomerSegmentId, customer: CustomerData): List<JobParameters> {
|
||||
|
||||
return customer.accounts.flatMap { account ->
|
||||
return account.allowedJobs.filter { it.jobName == segmentId.id }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -31,10 +31,7 @@ open class Kontoverbindung(
|
|||
Kreditinstitutskennung(bankCountryCode, bankCode)
|
||||
), Existenzstatus.Mandatory) {
|
||||
|
||||
constructor(bank: BankData, customer: CustomerData, account: AccountData?)
|
||||
: this(bank, customer, account?.subAccountAttribute)
|
||||
|
||||
constructor(bank: BankData, customer: CustomerData, subAccountAttribute: String?)
|
||||
: this(bank.countryCode, bank.bankCode, customer.customerId, subAccountAttribute)
|
||||
constructor(account: AccountData)
|
||||
: this(account.bankCountryCode, account.bankCode, account.accountIdentifier, account.subAccountAttribute)
|
||||
|
||||
}
|
|
@ -33,9 +33,8 @@ open class KontoverbindungInternational(
|
|||
Kreditinstitutskennung(bankCountryCode ?: 0, bankCode ?: "", if (bankCountryCode != null && bankCode != null) Existenzstatus.Optional else Existenzstatus.NotAllowed)
|
||||
), Existenzstatus.Mandatory) {
|
||||
|
||||
constructor(bank: BankData, customer: CustomerData, account: AccountData?)
|
||||
: this(bank, customer, account?.subAccountAttribute)
|
||||
constructor(account: AccountData, bank: BankData) : this(account, bank.bic)
|
||||
|
||||
constructor(bank: BankData, customer: CustomerData, subAccountAttribute: String?)
|
||||
: this(customer.iban, bank.bic, bank.countryCode, bank.bankCode, customer.customerId, subAccountAttribute)
|
||||
constructor(account: AccountData, bic: String)
|
||||
: this(account.iban, bic, account.bankCountryCode, account.bankCode, account.accountIdentifier, account.subAccountAttribute)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.sepa
|
||||
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.fints.model.AccountData
|
||||
import net.dankito.fints.model.BankTransferData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
|
||||
|
@ -9,6 +10,7 @@ open class SepaEinzelueberweisung(
|
|||
segmentNumber: Int,
|
||||
sepaDescriptorUrn: String,
|
||||
debitor: CustomerData,
|
||||
account: AccountData,
|
||||
debitorBic: String,
|
||||
data: BankTransferData,
|
||||
messageCreator: ISepaMessageCreator = SepaMessageCreator()
|
||||
|
@ -19,12 +21,12 @@ open class SepaEinzelueberweisung(
|
|||
1,
|
||||
sepaDescriptorUrn,
|
||||
"pain.001.001.03.xml",
|
||||
debitor.iban ?: "", // TODO: what to do if iban is not set?
|
||||
account.iban ?: "", // TODO: what to do if iban is not set?
|
||||
debitorBic,
|
||||
mapOf(
|
||||
SepaMessageCreator.NumberOfTransactionsKey to "1", // TODO: may someday support more then one transaction per file
|
||||
"DebitorName" to messageCreator.convertToAllowedCharacters(debitor.name),
|
||||
"DebitorIban" to debitor.iban!!,
|
||||
"DebitorIban" to account.iban!!,
|
||||
"DebitorBic" to debitorBic,
|
||||
"CreditorName" to messageCreator.convertToAllowedCharacters(data.creditorName),
|
||||
"CreditorIban" to data.creditorIban,
|
||||
|
|
|
@ -64,8 +64,8 @@ open class TanGeneratorTanMediumAnOderUmmelden(
|
|||
AlphanumerischesDatenelement(newActiveTanMedium.cardNumber, Existenzstatus.Mandatory),
|
||||
AlphanumerischesDatenelement(newActiveTanMedium.cardSequenceNumber, if (parameters.enteringCardSequenceNumberRequired) Existenzstatus.Mandatory else Existenzstatus.NotAllowed),
|
||||
if (segmentVersion > 1) NumerischesDatenelement(newActiveTanMedium.cardType, 2, if (parameters.enteringCardTypeAllowed) Existenzstatus.Optional else Existenzstatus.NotAllowed) else DoNotPrintDatenelement(),
|
||||
if (segmentVersion == 2) Kontoverbindung(bank, customer, customer.accounts.firstOrNull()) else DoNotPrintDatenelement(),
|
||||
if (segmentVersion >= 3 && parameters.accountInfoRequired) KontoverbindungInternational(bank, customer, customer.accounts.firstOrNull()) else DoNotPrintDatenelement(),
|
||||
if (segmentVersion == 2) Kontoverbindung(customer.accounts.first()) else DoNotPrintDatenelement(),
|
||||
if (segmentVersion >= 3 && parameters.accountInfoRequired) KontoverbindungInternational(customer.accounts.first(), bank) else DoNotPrintDatenelement(),
|
||||
if (segmentVersion >= 2) Datum(newActiveTanMedium.validFrom, Existenzstatus.Optional) else DoNotPrintDatenelement(),
|
||||
if (segmentVersion >= 2) Datum(newActiveTanMedium.validTo, Existenzstatus.Optional) else DoNotPrintDatenelement(),
|
||||
if (segmentVersion >= 3) AlphanumerischesDatenelement(iccsn, Existenzstatus.Optional, 19) else DoNotPrintDatenelement(),
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
import net.dankito.fints.model.AccountData
|
||||
import net.dankito.fints.model.GetTransactionsParameter
|
||||
|
||||
|
||||
|
@ -19,14 +18,6 @@ import net.dankito.fints.model.GetTransactionsParameter
|
|||
open class KontoumsaetzeZeitraumMt940Version5(
|
||||
segmentNumber: Int,
|
||||
parameter: GetTransactionsParameter,
|
||||
bank: BankData,
|
||||
customer: CustomerData,
|
||||
subAccountAttribute: String? = null
|
||||
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(
|
||||
5,
|
||||
segmentNumber,
|
||||
Kontoverbindung(bank.countryCode, bank.bankCode, customer.customerId, subAccountAttribute),
|
||||
parameter
|
||||
account: AccountData
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(5, segmentNumber, Kontoverbindung(account), parameter)
|
|
@ -1,8 +1,7 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
import net.dankito.fints.model.AccountData
|
||||
import net.dankito.fints.model.GetTransactionsParameter
|
||||
|
||||
|
||||
|
@ -19,14 +18,7 @@ import net.dankito.fints.model.GetTransactionsParameter
|
|||
open class KontoumsaetzeZeitraumMt940Version6(
|
||||
segmentNumber: Int,
|
||||
parameter: GetTransactionsParameter,
|
||||
bank: BankData,
|
||||
customer: CustomerData,
|
||||
subAccountAttribute: String? = null
|
||||
account: AccountData
|
||||
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(
|
||||
6,
|
||||
segmentNumber,
|
||||
Kontoverbindung(bank.countryCode, bank.bankCode, customer.customerId, subAccountAttribute),
|
||||
parameter
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(6, segmentNumber, Kontoverbindung(account), parameter)
|
|
@ -1,8 +1,8 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.umsaetze
|
||||
|
||||
import net.dankito.fints.messages.datenelementgruppen.implementierte.account.KontoverbindungInternational
|
||||
import net.dankito.fints.model.AccountData
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
import net.dankito.fints.model.GetTransactionsParameter
|
||||
|
||||
|
||||
|
@ -20,12 +20,6 @@ open class KontoumsaetzeZeitraumMt940Version7(
|
|||
segmentNumber: Int,
|
||||
parameter: GetTransactionsParameter,
|
||||
bank: BankData,
|
||||
customer: CustomerData,
|
||||
subAccountAttribute: String? = null // TODO: move to CustomerData.accounts
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(
|
||||
7,
|
||||
segmentNumber,
|
||||
KontoverbindungInternational(bank, customer, subAccountAttribute),
|
||||
parameter
|
||||
account: AccountData
|
||||
)
|
||||
: KontoumsaetzeZeitraumMt940Base(7, segmentNumber, KontoverbindungInternational(account, bank), parameter)
|
|
@ -8,21 +8,19 @@ import net.dankito.fints.messages.datenelementgruppen.implementierte.Segmentkopf
|
|||
import net.dankito.fints.messages.datenelementgruppen.implementierte.account.Kontoverbindung
|
||||
import net.dankito.fints.messages.segmente.Segment
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.fints.model.BankData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
import net.dankito.fints.model.AccountData
|
||||
|
||||
|
||||
open class Saldenabfrage(
|
||||
segmentNumber: Int,
|
||||
bank: BankData,
|
||||
customer: CustomerData, // TODO: pass AccountData instead
|
||||
account: AccountData,
|
||||
allAccounts: Boolean = false,
|
||||
maxAmountEntries: Int? = null,
|
||||
continuationId: String? = null
|
||||
)
|
||||
: Segment(listOf(
|
||||
Segmentkopf(CustomerSegmentId.Balance, 5, segmentNumber),
|
||||
Kontoverbindung(bank.countryCode, bank.bankCode, customer.customerId),
|
||||
Kontoverbindung(account),
|
||||
AlleKonten(allAccounts, Existenzstatus.Mandatory),
|
||||
MaximaleAnzahlEintraege(maxAmountEntries, Existenzstatus.Optional),
|
||||
Aufsetzpunkt(continuationId, Existenzstatus.Optional)
|
||||
|
|
|
@ -10,7 +10,6 @@ open class CustomerData(
|
|||
var pin: String,
|
||||
val userId: String = customerId,
|
||||
var name: String = "",
|
||||
var iban: String? = null,
|
||||
val accounts: List<AccountData> = mutableListOf(),
|
||||
var updVersion: Int = UPDVersion.VersionNotReceivedYet,
|
||||
var supportedTanProcedures: List<TanProcedure> = listOf(),
|
||||
|
|
|
@ -9,6 +9,7 @@ import net.dankito.fints.messages.datenelemente.implementierte.tan.TanEinsatzOpt
|
|||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse
|
||||
import net.dankito.fints.messages.segmente.id.CustomerSegmentId
|
||||
import net.dankito.fints.model.*
|
||||
import net.dankito.fints.model.mapper.BankDataMapper
|
||||
import net.dankito.fints.response.client.FinTsClientResponse
|
||||
|
@ -101,7 +102,6 @@ class FinTsClientTest {
|
|||
assertThat(Bank.supportedLanguages).isNotEmpty() // supported languages are now known
|
||||
|
||||
assertThat(Customer.name).isNotEmpty()
|
||||
assertThat(Customer.iban).isNotNull()
|
||||
assertThat(Customer.supportedTanProcedures).isNotEmpty()
|
||||
assertThat(Customer.selectedLanguage).isNotEqualTo(Dialogsprache.Default) // language is set now
|
||||
assertThat(Customer.customerSystemId).isNotEqualTo(KundensystemStatus.SynchronizingCustomerSystemId) // customer system id is now set
|
||||
|
@ -128,10 +128,15 @@ class FinTsClientTest {
|
|||
@Test
|
||||
fun getTransactions() {
|
||||
|
||||
// given
|
||||
underTest.addAccount(Bank, Customer) // retrieve basic data, e.g. accounts
|
||||
val account = underTest.getBestAccountForRetrievingTransactions(Customer)
|
||||
assertThat(account).describedAs("We need at least one account that supports retrieving account transactions (${CustomerSegmentId.AccountTransactionsMt940.id})").isNotNull()
|
||||
|
||||
// when
|
||||
|
||||
// some banks support retrieving account transactions of last 90 days without TAN
|
||||
val result = underTest.tryGetTransactionsOfLast90DaysWithoutTan(Bank, Customer, false)
|
||||
val result = underTest.tryGetTransactionsOfLast90DaysWithoutTan(Bank, Customer, account!!, false)
|
||||
|
||||
|
||||
// then
|
||||
|
@ -177,17 +182,21 @@ class FinTsClientTest {
|
|||
fun testBankTransfer() {
|
||||
|
||||
// given
|
||||
underTest.addAccount(Bank, Customer)
|
||||
underTest.addAccount(Bank, Customer) // retrieve basic data, e.g. accounts
|
||||
|
||||
// now IBAN should be set
|
||||
assertThat(Customer.iban).describedAs("Customer's IBAN should now be set").isNotNull()
|
||||
// we need at least one account that supports cash transfer
|
||||
val account = Customer.accounts.firstOrNull { it.allowedJobNames.contains(CustomerSegmentId.SepaBankTransfer.id) }
|
||||
assertThat(account).describedAs("We need at least one account that supports cash transfer (${CustomerSegmentId.SepaBankTransfer.id})").isNotNull()
|
||||
|
||||
// IBAN should be set
|
||||
assertThat(account?.iban).describedAs("Account IBAN must be set").isNotNull()
|
||||
|
||||
// transfer 1 cent to yourself. Transferring money to oneself also doesn't require to enter a TAN according to PSD2
|
||||
val BankTransferData = BankTransferData(Customer.name, Customer.iban!!, Bank.bic, 0.01.toBigDecimal(), "Give it to me baby")
|
||||
val BankTransferData = BankTransferData(Customer.name, account?.iban!!, Bank.bic, 0.01.toBigDecimal(), "Give it to me baby")
|
||||
|
||||
|
||||
// when
|
||||
val result = underTest.doBankTransfer(BankTransferData, Bank, Customer)
|
||||
val result = underTest.doBankTransfer(BankTransferData, Bank, Customer, account)
|
||||
|
||||
// then
|
||||
assertThat(result.isSuccessful).isTrue()
|
||||
|
|
|
@ -3,8 +3,8 @@ package net.dankito.fints
|
|||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Datum
|
||||
import net.dankito.fints.messages.datenelemente.abgeleiteteformate.Laenderkennzeichen
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache
|
||||
import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion
|
||||
import net.dankito.fints.model.*
|
||||
import net.dankito.fints.response.segments.AccountType
|
||||
import net.dankito.fints.response.segments.ChangeTanMediaParameters
|
||||
import net.dankito.fints.response.segments.JobParameters
|
||||
import java.math.BigDecimal
|
||||
|
@ -38,6 +38,12 @@ abstract class FinTsTestBase {
|
|||
|
||||
val Customer = CustomerData(CustomerId, Pin, selectedTanProcedure = TanProcedure("chipTAN-optisch", SecurityFunction, TanProcedureType.ChipTanOptisch), selectedLanguage = Language)
|
||||
|
||||
val Currency = "EUR"
|
||||
|
||||
val AccountHolderName = "Martina Musterfrau"
|
||||
|
||||
val Account = AccountData(CustomerId, null, BankCountryCode, BankCode, Iban, CustomerId, AccountType.Girokonto, Currency, AccountHolderName, null, null, listOf(), listOf())
|
||||
|
||||
const val ProductName = "FinTS-TestClient25Stellen"
|
||||
|
||||
const val ProductVersion = "1"
|
||||
|
|
|
@ -38,7 +38,6 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
@After
|
||||
fun tearDown() {
|
||||
Bank.supportedJobs = listOf()
|
||||
Customer.accounts = listOf()
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,7 +121,7 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
fun createGetTransactionsMessage_JobIsNotAllowed() {
|
||||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(), Bank, Customer, Product, DialogData.DialogInitDialogData)
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(), Bank, Customer, Account, Product, DialogData.DialogInitDialogData)
|
||||
|
||||
// then
|
||||
assertThat(result.isJobAllowed).isFalse()
|
||||
|
@ -136,10 +135,10 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
val getTransactionsJobWithPreviousVersion = JobParameters("HKKAZ", 1, 1, null, "HKKAZ:72:4")
|
||||
Bank.supportedJobs = listOf(getTransactionsJob)
|
||||
val account = AccountData(CustomerId, null, BankCountryCode, BankCode, null, CustomerId, AccountType.Girokonto, "EUR", "", null, null, listOf(getTransactionsJob.jobName), listOf(getTransactionsJobWithPreviousVersion))
|
||||
Customer.accounts = listOf(account)
|
||||
Customer.addAccount(account)
|
||||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(), Bank, Customer, Product, DialogData.DialogInitDialogData)
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(), Bank, Customer, account, Product, DialogData.DialogInitDialogData)
|
||||
|
||||
// then
|
||||
assertThat(result.isJobAllowed).isTrue()
|
||||
|
@ -153,14 +152,14 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
val getTransactionsJob = JobParameters("HKKAZ", 1, 1, null, "HKKAZ:73:5")
|
||||
Bank.supportedJobs = listOf(getTransactionsJob)
|
||||
val account = AccountData(CustomerId, null, BankCountryCode, BankCode, null, CustomerId, AccountType.Girokonto, "EUR", "", null, null, listOf(getTransactionsJob.jobName), listOf(getTransactionsJob))
|
||||
Customer.accounts = listOf(account)
|
||||
Customer.addAccount(account)
|
||||
|
||||
val fromDate = LocalDate.of(2019, Month.AUGUST, 6).asUtilDate()
|
||||
val toDate = LocalDate.of(2019, Month.OCTOBER, 21).asUtilDate()
|
||||
val maxCountEntries = 99
|
||||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(false, fromDate, toDate, maxCountEntries), Bank, Customer, Product, DialogData.DialogInitDialogData)
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(false, fromDate, toDate, maxCountEntries), Bank, Customer, account, Product, DialogData.DialogInitDialogData)
|
||||
|
||||
// then
|
||||
assertThat(result.createdMessage).isNotNull()
|
||||
|
@ -183,7 +182,7 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
val getTransactionsJob = JobParameters("HKKAZ", 1, 1, null, "HKKAZ:73:5")
|
||||
Bank.supportedJobs = listOf(getTransactionsJob)
|
||||
val account = AccountData(CustomerId, null, BankCountryCode, BankCode, null, CustomerId, AccountType.Girokonto, "EUR", "", null, null, listOf(getTransactionsJob.jobName), listOf(getTransactionsJob))
|
||||
Customer.accounts = listOf(account)
|
||||
Customer.addAccount(account)
|
||||
|
||||
val fromDate = LocalDate.of(2019, Month.AUGUST, 6).asUtilDate()
|
||||
val toDate = LocalDate.of(2019, Month.OCTOBER, 21).asUtilDate()
|
||||
|
@ -191,7 +190,7 @@ class MessageBuilderTest : FinTsTestBase() {
|
|||
val continuationId = "9345-10-26-11.52.15.693455"
|
||||
|
||||
// when
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(false, fromDate, toDate, maxCountEntries, false, continuationId), Bank, Customer, Product, DialogData.DialogInitDialogData)
|
||||
val result = underTest.createGetTransactionsMessage(GetTransactionsParameter(false, fromDate, toDate, maxCountEntries, false, continuationId), Bank, Customer, account, Product, DialogData.DialogInitDialogData)
|
||||
|
||||
// then
|
||||
assertThat(result.createdMessage).isNotNull()
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package net.dankito.fints.messages.segmente.implementierte.sepa
|
||||
|
||||
import net.dankito.fints.model.AccountData
|
||||
import net.dankito.fints.model.BankTransferData
|
||||
import net.dankito.fints.model.CustomerData
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
class SepaEinzelueberweisungTest {
|
||||
|
||||
@Test
|
||||
|
@ -23,7 +25,8 @@ class SepaEinzelueberweisungTest {
|
|||
|
||||
val underTest = SepaEinzelueberweisung(segmentNumber,
|
||||
"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03",
|
||||
CustomerData("", "", "", debitorName, debitorIban),
|
||||
CustomerData("", "", "", debitorName),
|
||||
AccountData("", null, 0, "", debitorIban, "", null, null, "", null, null, listOf()),
|
||||
debitorBic,
|
||||
BankTransferData(creditorName, creditorIban, creditorBic, amount, usage)
|
||||
)
|
||||
|
|
|
@ -10,8 +10,7 @@ class SaldenabfrageTest : FinTsTestBase() {
|
|||
fun format_NotAllAccounts() {
|
||||
|
||||
// given
|
||||
val underTest =
|
||||
Saldenabfrage(3, Bank, Customer, false)
|
||||
val underTest = Saldenabfrage(3, Account, false)
|
||||
|
||||
// when
|
||||
val result = underTest.format()
|
||||
|
@ -24,8 +23,7 @@ class SaldenabfrageTest : FinTsTestBase() {
|
|||
fun format_AllAccounts() {
|
||||
|
||||
// given
|
||||
val underTest =
|
||||
Saldenabfrage(3, Bank, Customer, true)
|
||||
val underTest = Saldenabfrage(3, Account, true)
|
||||
|
||||
// when
|
||||
val result = underTest.format()
|
||||
|
|
Loading…
Reference in New Issue