Implemented checking if bank supports setting count max entries. Had to adjust Jackson serialization so that and not just JobParameters gets saved and restored and to implement a lot of default constructors for this
This commit is contained in:
parent
4ed3d44b9e
commit
b403557f2d
|
@ -12,15 +12,15 @@ import net.dankito.banking.fints.messages.segmente.Segment
|
||||||
import net.dankito.banking.fints.messages.segmente.SegmentNumberGenerator
|
import net.dankito.banking.fints.messages.segmente.SegmentNumberGenerator
|
||||||
import net.dankito.banking.fints.messages.segmente.Synchronisierung
|
import net.dankito.banking.fints.messages.segmente.Synchronisierung
|
||||||
import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId
|
import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId
|
||||||
|
import net.dankito.banking.fints.messages.segmente.id.ISegmentId
|
||||||
import net.dankito.banking.fints.messages.segmente.implementierte.*
|
import net.dankito.banking.fints.messages.segmente.implementierte.*
|
||||||
import net.dankito.banking.fints.messages.segmente.implementierte.sepa.SepaBankTransferBase
|
import net.dankito.banking.fints.messages.segmente.implementierte.sepa.SepaBankTransferBase
|
||||||
import net.dankito.banking.fints.messages.segmente.implementierte.tan.TanGeneratorListeAnzeigen
|
import net.dankito.banking.fints.messages.segmente.implementierte.tan.TanGeneratorListeAnzeigen
|
||||||
import net.dankito.banking.fints.messages.segmente.implementierte.tan.TanGeneratorTanMediumAnOderUmmelden
|
import net.dankito.banking.fints.messages.segmente.implementierte.tan.TanGeneratorTanMediumAnOderUmmelden
|
||||||
import net.dankito.banking.fints.messages.segmente.implementierte.umsaetze.*
|
import net.dankito.banking.fints.messages.segmente.implementierte.umsaetze.*
|
||||||
import net.dankito.banking.fints.model.*
|
import net.dankito.banking.fints.model.*
|
||||||
import net.dankito.banking.fints.response.segments.JobParameters
|
import net.dankito.banking.fints.response.InstituteSegmentId
|
||||||
import net.dankito.banking.fints.response.segments.SepaAccountInfoParameters
|
import net.dankito.banking.fints.response.segments.*
|
||||||
import net.dankito.banking.fints.response.segments.TanResponse
|
|
||||||
import net.dankito.banking.fints.util.FinTsUtils
|
import net.dankito.banking.fints.util.FinTsUtils
|
||||||
import net.dankito.utils.multiplatform.Date
|
import net.dankito.utils.multiplatform.Date
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
@ -152,20 +152,36 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
||||||
val result = supportsGetTransactionsMt940(account)
|
val result = supportsGetTransactionsMt940(account)
|
||||||
|
|
||||||
if (result.isJobVersionSupported) {
|
if (result.isJobVersionSupported) {
|
||||||
val transactionsJob = if (result.isAllowed(7)) KontoumsaetzeZeitraumMt940Version7(generator.resetSegmentNumber(2), parameter, dialogContext.bank, account)
|
return createGetTransactionsMessageMt940(result, parameter, dialogContext, account)
|
||||||
else if (result.isAllowed(6)) KontoumsaetzeZeitraumMt940Version6(generator.resetSegmentNumber(2), parameter, account)
|
|
||||||
else KontoumsaetzeZeitraumMt940Version5(generator.resetSegmentNumber(2), parameter, account)
|
|
||||||
|
|
||||||
val segments = mutableListOf<Segment>(transactionsJob)
|
|
||||||
|
|
||||||
addTanSegmentIfRequired(CustomerSegmentId.AccountTransactionsMt940, dialogContext, segments)
|
|
||||||
|
|
||||||
return createSignedMessageBuilderResult(dialogContext, segments)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun createGetTransactionsMessageMt940(result: MessageBuilderResult, parameter: GetTransactionsParameter,
|
||||||
|
dialogContext: DialogContext, account: AccountData): MessageBuilderResult {
|
||||||
|
|
||||||
|
if (parameter.maxCountEntries != null) {
|
||||||
|
parameter.isSettingMaxCountEntriesAllowedByBank = determineIsSettingMaxCountEntriesAllowed(dialogContext.bank, InstituteSegmentId.AccountTransactionsMt940Parameters, listOf(5, 6, 7))
|
||||||
|
}
|
||||||
|
|
||||||
|
val transactionsJob = if (result.isAllowed(7)) KontoumsaetzeZeitraumMt940Version7(generator.resetSegmentNumber(2), parameter, dialogContext.bank, account)
|
||||||
|
else if (result.isAllowed(6)) KontoumsaetzeZeitraumMt940Version6(generator.resetSegmentNumber(2), parameter, account)
|
||||||
|
else KontoumsaetzeZeitraumMt940Version5(generator.resetSegmentNumber(2), parameter, account)
|
||||||
|
|
||||||
|
val segments = mutableListOf<Segment>(transactionsJob)
|
||||||
|
|
||||||
|
addTanSegmentIfRequired(CustomerSegmentId.AccountTransactionsMt940, dialogContext, segments)
|
||||||
|
|
||||||
|
return createSignedMessageBuilderResult(dialogContext, segments)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun determineIsSettingMaxCountEntriesAllowed(bank: BankData, segmentId: ISegmentId, supportedJobVersions: List<Int>): Boolean {
|
||||||
|
return bank.supportedJobs.filterIsInstance<RetrieveAccountTransactionsInMt940Parameters>()
|
||||||
|
.filter { it.segmentId == segmentId.id && supportedJobVersions.contains(it.segmentVersion) }
|
||||||
|
.firstOrNull { it.settingCountEntriesAllowed } != null
|
||||||
|
}
|
||||||
|
|
||||||
open fun supportsGetTransactions(account: AccountData): Boolean {
|
open fun supportsGetTransactions(account: AccountData): Boolean {
|
||||||
return supportsGetTransactionsMt940(account).isJobVersionSupported
|
return supportsGetTransactionsMt940(account).isJobVersionSupported
|
||||||
}
|
}
|
||||||
|
@ -255,9 +271,7 @@ open class MessageBuilder(protected val generator: ISegmentNumberGenerator = Seg
|
||||||
|
|
||||||
val segmentId = if (data.instantPayment) CustomerSegmentId.SepaInstantPaymentBankTransfer else CustomerSegmentId.SepaBankTransfer
|
val segmentId = if (data.instantPayment) CustomerSegmentId.SepaInstantPaymentBankTransfer else CustomerSegmentId.SepaBankTransfer
|
||||||
|
|
||||||
val messageBuilderResultAndNullableUrn = supportsBankTransferAndSepaVersion(dialogContext.bank, account, segmentId)
|
val (result, urn) = supportsBankTransferAndSepaVersion(dialogContext.bank, account, segmentId)
|
||||||
val result = messageBuilderResultAndNullableUrn.first
|
|
||||||
val urn = messageBuilderResultAndNullableUrn.second
|
|
||||||
|
|
||||||
if (result.isJobVersionSupported && urn != null) {
|
if (result.isJobVersionSupported && urn != null) {
|
||||||
val segments = mutableListOf<Segment>(SepaBankTransferBase(segmentId, generator.resetSegmentNumber(2),
|
val segments = mutableListOf<Segment>(SepaBankTransferBase(segmentId, generator.resetSegmentNumber(2),
|
||||||
|
|
|
@ -34,6 +34,6 @@ abstract class KontoumsaetzeZeitraumMt940Base(
|
||||||
AlleKonten(false, Existenzstatus.Mandatory), // currently no supported, we retrieve account transactions account by account (most banks don't support AlleKonten anyway)
|
AlleKonten(false, Existenzstatus.Mandatory), // currently no supported, we retrieve account transactions account by account (most banks don't support AlleKonten anyway)
|
||||||
Datum(parameter.fromDate, Existenzstatus.Optional),
|
Datum(parameter.fromDate, Existenzstatus.Optional),
|
||||||
Datum(parameter.toDate, Existenzstatus.Optional),
|
Datum(parameter.toDate, Existenzstatus.Optional),
|
||||||
MaximaleAnzahlEintraege(parameter.maxCountEntries, Existenzstatus.Optional), // > 0. O: „Eingabe Anzahl Einträge erlaubt“ (BPD) = „J“. N: sonst
|
MaximaleAnzahlEintraege(parameter.maxCountEntriesIfSettingItIsAllowed, if (parameter.isSettingMaxCountEntriesAllowedByBank) Existenzstatus.Optional else Existenzstatus.NotAllowed), // > 0. O: „Eingabe Anzahl Einträge erlaubt“ (BPD) = „J“. N: sonst
|
||||||
Aufsetzpunkt(null, Existenzstatus.Optional) // will be set dynamically, see MessageBuilder.rebuildMessageWithContinuationId(); M: vom Institut wurde ein Aufsetzpunkt rückgemeldet. N: sonst
|
Aufsetzpunkt(null, Existenzstatus.Optional) // will be set dynamically, see MessageBuilder.rebuildMessageWithContinuationId(); M: vom Institut wurde ein Aufsetzpunkt rückgemeldet. N: sonst
|
||||||
))
|
))
|
|
@ -7,7 +7,22 @@ open class GetTransactionsParameter(
|
||||||
val alsoRetrieveBalance: Boolean = true,
|
val alsoRetrieveBalance: Boolean = true,
|
||||||
val fromDate: Date? = null,
|
val fromDate: Date? = null,
|
||||||
val toDate: Date? = null,
|
val toDate: Date? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Be aware this is by far not supported by all banks.
|
||||||
|
*
|
||||||
|
* And it depends on the actual job if setting maxCountEntries is supported or not.
|
||||||
|
*
|
||||||
|
* // TODO: set a parameter in response if maxCountEntries is set but bank doesn't support it.
|
||||||
|
*/
|
||||||
val maxCountEntries: Int? = null,
|
val maxCountEntries: Int? = null,
|
||||||
val abortIfTanIsRequired: Boolean = false,
|
val abortIfTanIsRequired: Boolean = false,
|
||||||
val retrievedChunkListener: ((Collection<AccountTransaction>) -> Unit)? = null
|
val retrievedChunkListener: ((Collection<AccountTransaction>) -> Unit)? = null
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
internal var isSettingMaxCountEntriesAllowedByBank = false
|
||||||
|
|
||||||
|
internal val maxCountEntriesIfSettingItIsAllowed: Int?
|
||||||
|
get() = if (isSettingMaxCountEntriesAllowedByBank) maxCountEntries else null
|
||||||
|
|
||||||
|
}
|
|
@ -63,8 +63,10 @@ open class SepaAccountInfoParameters(
|
||||||
* zugelassenen SEPA pain messages.
|
* zugelassenen SEPA pain messages.
|
||||||
*/
|
*/
|
||||||
val supportedSepaFormats: List<String>
|
val supportedSepaFormats: List<String>
|
||||||
)
|
) : JobParameters(parameters) {
|
||||||
: JobParameters(parameters) {
|
|
||||||
|
internal constructor() : this(JobParameters(), false, false, false, false, -1, listOf()) // for object deserializers
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val CountReservedUsageLengthNotSet = 0
|
const val CountReservedUsageLengthNotSet = 0
|
||||||
|
|
|
@ -4,5 +4,8 @@ package net.dankito.banking.fints.response.segments
|
||||||
open class TanInfo(
|
open class TanInfo(
|
||||||
parameters: JobParameters,
|
parameters: JobParameters,
|
||||||
val tanProcedureParameters: TwoStepTanProcedureParameters
|
val tanProcedureParameters: TwoStepTanProcedureParameters
|
||||||
)
|
) : JobParameters(parameters) {
|
||||||
: JobParameters(parameters)
|
|
||||||
|
internal constructor() : this(JobParameters(), TwoStepTanProcedureParameters()) // for object deserializers
|
||||||
|
|
||||||
|
}
|
|
@ -28,6 +28,12 @@ open class TanProcedureParameters(
|
||||||
val countSupportedActiveTanMedia: Int?
|
val countSupportedActiveTanMedia: Int?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
||||||
|
internal constructor() : this(Sicherheitsfunktion.Klartext, TanProcess.TanProcess1, "", null, null, "", -1,
|
||||||
|
AllowedTanFormat.Alphanumeric, "", -1, false, TanZeitUndDialogbezug.NotSupported, false, SmsAbbuchungskontoErforderlich.SmsAbbuchungskontoDarfNichtAngegebenWerden, AuftraggeberkontoErforderlich.AuftraggeberkontoDarfNichtAngegebenWerden,
|
||||||
|
false, false, Initialisierungsmodus.InitialisierungsverfahrenMitKlartextPinOhneTan, BezeichnungDesTanMediumsErforderlich.BezeichnungDesTanMediumsDarfNichtAngegebenWerden, false, null) // for object deserializers
|
||||||
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "$procedureName $technicalTanProcedureIdentification"
|
return "$procedureName $technicalTanProcedureIdentification"
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,8 @@ open class TwoStepTanProcedureParameters(
|
||||||
val moreThanOneTanDependentJobPerMessageAllowed: Boolean,
|
val moreThanOneTanDependentJobPerMessageAllowed: Boolean,
|
||||||
val jobHashValue: String, // not evaluated for PIN/TAN
|
val jobHashValue: String, // not evaluated for PIN/TAN
|
||||||
val procedureParameters: List<TanProcedureParameters>
|
val procedureParameters: List<TanProcedureParameters>
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
internal constructor() : this(false, false, "", listOf()) // for object deserializers
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,20 @@
|
||||||
package net.dankito.banking.util
|
package net.dankito.banking.util
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import net.dankito.banking.util.persistence.JacksonClassNameIdResolver
|
||||||
import net.dankito.utils.multiplatform.File
|
import net.dankito.utils.multiplatform.File
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
|
||||||
open class JacksonJsonSerializer(
|
open class JacksonJsonSerializer(
|
||||||
protected val serializer: net.dankito.utils.serialization.ISerializer = net.dankito.utils.serialization.JacksonJsonSerializer()
|
protected val serializer: net.dankito.utils.serialization.ISerializer = net.dankito.utils.serialization.JacksonJsonSerializer { objectMapper ->
|
||||||
|
val typeResolver = ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE)
|
||||||
|
typeResolver.init(JsonTypeInfo.Id.CLASS, JacksonClassNameIdResolver())
|
||||||
|
typeResolver.inclusion(JsonTypeInfo.As.PROPERTY)
|
||||||
|
typeResolver.typeProperty("@CLASS")
|
||||||
|
objectMapper.setDefaultTyping(typeResolver)
|
||||||
|
}
|
||||||
) : ISerializer {
|
) : ISerializer {
|
||||||
|
|
||||||
override fun serializeObject(obj: Any, outputFile: File) {
|
override fun serializeObject(obj: Any, outputFile: File) {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package net.dankito.banking.util.persistence
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.DatabindContext
|
||||||
|
import com.fasterxml.jackson.databind.JavaType
|
||||||
|
import com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver
|
||||||
|
import com.fasterxml.jackson.databind.type.SimpleType
|
||||||
|
import com.fasterxml.jackson.databind.type.TypeFactory
|
||||||
|
import net.dankito.banking.fints.response.segments.JobParameters
|
||||||
|
import net.dankito.banking.fints.response.segments.RetrieveAccountTransactionsInMt940Parameters
|
||||||
|
import net.dankito.banking.fints.response.segments.SepaAccountInfoParameters
|
||||||
|
import kotlin.reflect.jvm.jvmName
|
||||||
|
|
||||||
|
|
||||||
|
open class JacksonClassNameIdResolver : ClassNameIdResolver(SimpleType.construct(JobParameters::class.java), TypeFactory.defaultInstance()) {
|
||||||
|
|
||||||
|
override fun idFromValue(value: Any?): String {
|
||||||
|
if (value is RetrieveAccountTransactionsInMt940Parameters) {
|
||||||
|
return RetrieveAccountTransactionsInMt940Parameters::class.jvmName
|
||||||
|
}
|
||||||
|
else if (value is SepaAccountInfoParameters) {
|
||||||
|
return SepaAccountInfoParameters::class.jvmName
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.idFromValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun typeFromId(context: DatabindContext?, id: String?): JavaType {
|
||||||
|
return when (id) {
|
||||||
|
RetrieveAccountTransactionsInMt940Parameters::class.jvmName -> _typeFactory.constructSpecializedType(_baseType, RetrieveAccountTransactionsInMt940Parameters::class.java)
|
||||||
|
SepaAccountInfoParameters::class.jvmName -> _typeFactory.constructSpecializedType(_baseType, SepaAccountInfoParameters::class.java)
|
||||||
|
else -> super.typeFromId(context, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue