Renamed Turnover to StatementLine and TransactionDetails to InformationToAccountOwner

This commit is contained in:
dankito 2020-05-21 18:12:34 +02:00
parent d33de9a009
commit 676eb721e7
5 changed files with 61 additions and 60 deletions

View File

@ -7,7 +7,7 @@ import net.dankito.banking.fints.transactions.mt940.Mt940Parser
import net.dankito.banking.fints.transactions.mt940.model.AccountStatement import net.dankito.banking.fints.transactions.mt940.model.AccountStatement
import net.dankito.banking.fints.transactions.mt940.model.Balance import net.dankito.banking.fints.transactions.mt940.model.Balance
import net.dankito.banking.fints.transactions.mt940.model.Transaction import net.dankito.banking.fints.transactions.mt940.model.Transaction
import net.dankito.banking.fints.transactions.mt940.model.Turnover import net.dankito.banking.fints.transactions.mt940.model.StatementLine
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.math.BigDecimal import java.math.BigDecimal
@ -45,15 +45,15 @@ open class Mt940AccountTransactionsParser @JvmOverloads constructor(
protected open fun mapToAccountTransaction(statement: AccountStatement, transaction: Transaction, account: AccountData): AccountTransaction { protected open fun mapToAccountTransaction(statement: AccountStatement, transaction: Transaction, account: AccountData): AccountTransaction {
return AccountTransaction( return AccountTransaction(
mapAmount(transaction.turnover), mapAmount(transaction.statementLine),
statement.closingBalance.currency, statement.closingBalance.currency,
transaction.details?.sepaUsage ?: transaction.details?.usage ?: "", transaction.information?.sepaUsage ?: transaction.information?.usage ?: "",
transaction.turnover.bookingDate ?: statement.closingBalance.bookingDate, transaction.statementLine.bookingDate ?: statement.closingBalance.bookingDate,
transaction.details?.otherPartyName, transaction.information?.otherPartyName,
transaction.details?.otherPartyBankCode, transaction.information?.otherPartyBankCode,
transaction.details?.otherPartyAccountId, transaction.information?.otherPartyAccountId,
transaction.details?.bookingText, transaction.information?.bookingText,
transaction.turnover.valueDate, transaction.statementLine.valueDate,
mapAmount(statement.openingBalance), // TODO: that's not true, these are the opening and closing balance of mapAmount(statement.openingBalance), // TODO: that's not true, these are the opening and closing balance of
mapAmount(statement.closingBalance), // all transactions of this day, not this specific transaction's ones mapAmount(statement.closingBalance), // all transactions of this day, not this specific transaction's ones
account account
@ -70,8 +70,8 @@ open class Mt940AccountTransactionsParser @JvmOverloads constructor(
/** /**
* In MT940 amounts are always stated as a positive number and flag isCredit decides if it's a credit or debit. * In MT940 amounts are always stated as a positive number and flag isCredit decides if it's a credit or debit.
*/ */
protected open fun mapAmount(turnover: Turnover): BigDecimal { protected open fun mapAmount(statementLine: StatementLine): BigDecimal {
return mapAmount(turnover.amount, turnover.isCredit) return mapAmount(statementLine.amount, statementLine.isCredit)
} }
/** /**

View File

@ -29,21 +29,21 @@ open class Mt940Parser : IMt940Parser {
val AccountStatementFieldSeparatorPattern = Pattern.compile(":\\d\\d\\w?:") val AccountStatementFieldSeparatorPattern = Pattern.compile(":\\d\\d\\w?:")
val TransactionReferenceNumberCode = "20" const val TransactionReferenceNumberCode = "20"
val RelatedReferenceNumberCode = "21" const val RelatedReferenceNumberCode = "21"
val AccountIdentificationCode = "25" const val AccountIdentificationCode = "25"
val StatementNumberCode = "28C" const val StatementNumberCode = "28C"
val OpeningBalanceCode = "60" const val OpeningBalanceCode = "60"
val TransactionTurnoverCode = "61" const val StatementLineCode = "61"
val TransactionDetailsCode = "86" const val InformationToAccountOwnerCode = "86"
val ClosingBalanceCode = "62" const val ClosingBalanceCode = "62"
val DateFormat = SimpleDateFormat("yyMMdd") val DateFormat = SimpleDateFormat("yyMMdd")
@ -190,13 +190,13 @@ open class Mt940Parser : IMt940Parser {
val transactions = mutableListOf<Transaction>() val transactions = mutableListOf<Transaction>()
fieldsByCode.forEachIndexed { index, pair -> fieldsByCode.forEachIndexed { index, pair ->
if (pair.first == TransactionTurnoverCode) { if (pair.first == StatementLineCode) {
val turnover = parseTurnover(pair.second) val statementLine = parseStatementLine(pair.second)
val nextPair = if (index < fieldsByCode.size - 1) fieldsByCode.get(index + 1) else null val nextPair = if (index < fieldsByCode.size - 1) fieldsByCode.get(index + 1) else null
val details = if (nextPair?.first == TransactionDetailsCode) parseNullableTransactionDetails(nextPair.second) else null val information = if (nextPair?.first == InformationToAccountOwnerCode) parseNullableInformationToAccountOwner(nextPair.second) else null
transactions.add(Transaction(turnover, details)) transactions.add(Transaction(statementLine, information))
} }
} }
@ -220,7 +220,7 @@ open class Mt940Parser : IMt940Parser {
* 8 [//16x] (Reference of the Account Servicing Institution) * 8 [//16x] (Reference of the Account Servicing Institution)
* 9 [34x] (Supplementary Details) * 9 [34x] (Supplementary Details)
*/ */
protected open fun parseTurnover(fieldValue: String): Turnover { protected open fun parseStatementLine(fieldValue: String): StatementLine {
val valueDateString = fieldValue.substring(0, 6) val valueDateString = fieldValue.substring(0, 6)
val valueDate = parseMt940Date(valueDateString) val valueDate = parseMt940Date(valueDateString)
@ -275,28 +275,28 @@ open class Mt940Parser : IMt940Parser {
supplementaryDetails = bankReferenceAndSupplementaryDetails[1].trim() supplementaryDetails = bankReferenceAndSupplementaryDetails[1].trim()
} }
return Turnover(!!!isDebit, isCancellation, valueDate, bookingDate, null, amount, bookingKey, return StatementLine(!!!isDebit, isCancellation, valueDate, bookingDate, null, amount, bookingKey,
customerReference, bankReference, supplementaryDetails) customerReference, bankReference, supplementaryDetails)
} }
protected open fun parseNullableTransactionDetails(detailsString: String): TransactionDetails? { protected open fun parseNullableInformationToAccountOwner(informationToAccountOwnerString: String): InformationToAccountOwner? {
try { try {
val details = parseTransactionDetails(detailsString) val information = parseInformationToAccountOwner(informationToAccountOwnerString)
mapUsage(details) mapUsage(information)
return details return information
} catch (e: Exception) { } catch (e: Exception) {
log.error("Could not parse transaction details from field value '$detailsString'", e) log.error("Could not parse InformationToAccountOwner from field value '$informationToAccountOwnerString'", e)
} }
return null return null
} }
protected open fun parseTransactionDetails(detailsString: String): TransactionDetails { protected open fun parseInformationToAccountOwner(informationToAccountOwnerString: String): InformationToAccountOwner {
// e. g. starts with 0 -> Inlandszahlungsverkehr, starts with '3' -> Wertpapiergeschäft // e. g. starts with 0 -> Inlandszahlungsverkehr, starts with '3' -> Wertpapiergeschäft
// see Finanzdatenformate p. 209 - 215 // see Finanzdatenformate p. 209 - 215
val geschaeftsvorfallCode = detailsString.substring(0, 2) // TODO: may map val geschaeftsvorfallCode = informationToAccountOwnerString.substring(0, 2) // TODO: may map
val usage = StringBuilder() val usage = StringBuilder()
val otherPartyName = StringBuilder() val otherPartyName = StringBuilder()
@ -306,7 +306,7 @@ open class Mt940Parser : IMt940Parser {
var primaNotaNumber: String? = null var primaNotaNumber: String? = null
var textKeySupplement: String? = null var textKeySupplement: String? = null
detailsString.substring(3).split('?').forEach { subField -> informationToAccountOwnerString.substring(3).split('?').forEach { subField ->
if (subField.isNotEmpty()) { if (subField.isNotEmpty()) {
val fieldCode = subField.substring(0, 2).toInt() val fieldCode = subField.substring(0, 2).toInt()
val fieldValue = subField.substring(2) val fieldValue = subField.substring(2)
@ -326,11 +326,10 @@ open class Mt940Parser : IMt940Parser {
val otherPartyNameString = if (otherPartyName.isEmpty()) null else otherPartyName.toString() val otherPartyNameString = if (otherPartyName.isEmpty()) null else otherPartyName.toString()
val details = TransactionDetails( return InformationToAccountOwner(
usage.toString(), otherPartyNameString, otherPartyBankCode, otherPartyAccountId, usage.toString(), otherPartyNameString, otherPartyBankCode, otherPartyAccountId,
bookingText, primaNotaNumber, textKeySupplement bookingText, primaNotaNumber, textKeySupplement
) )
return details
} }
/** /**
@ -355,21 +354,21 @@ 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(details: TransactionDetails) { protected open fun mapUsage(information: InformationToAccountOwner) {
val usageParts = getUsageParts(details) val usageParts = getUsageParts(information)
usageParts.forEach { pair -> usageParts.forEach { pair ->
setUsageLineValue(details, pair.first, pair.second) setUsageLineValue(information, pair.first, pair.second)
} }
} }
protected open fun getUsageParts(details: TransactionDetails): MutableList<Pair<String, String>> { protected open fun getUsageParts(information: InformationToAccountOwner): MutableList<Pair<String, String>> {
val usage = details.usage val usage = information.usage
var previousMatchType = "" var previousMatchType = ""
var previousMatchEnd = 0 var previousMatchEnd = 0
val usageParts = mutableListOf<Pair<String, String>>() val usageParts = mutableListOf<Pair<String, String>>()
val matcher = UsageTypePattern.matcher(details.usage) val matcher = UsageTypePattern.matcher(information.usage)
while (matcher.find()) { while (matcher.find()) {
if (previousMatchEnd > 0) { if (previousMatchEnd > 0) {
@ -391,19 +390,19 @@ open class Mt940Parser : IMt940Parser {
return usageParts return usageParts
} }
protected open fun setUsageLineValue(details: TransactionDetails, usageType: String, typeValue: String) { protected open fun setUsageLineValue(information: InformationToAccountOwner, usageType: String, typeValue: String) {
when (usageType) { when (usageType) {
"EREF+" -> details.endToEndReference = typeValue "EREF+" -> information.endToEndReference = typeValue
"KREF+" -> details.customerReference = typeValue "KREF+" -> information.customerReference = typeValue
"MREF+" -> details.mandateReference = typeValue "MREF+" -> information.mandateReference = typeValue
"CRED+" -> details.creditorIdentifier = typeValue "CRED+" -> information.creditorIdentifier = typeValue
"DEBT+" -> details.originatorsIdentificationCode = typeValue "DEBT+" -> information.originatorsIdentificationCode = typeValue
"COAM+" -> details.compensationAmount = typeValue "COAM+" -> information.compensationAmount = typeValue
"OAMT+" -> details.originalAmount = typeValue "OAMT+" -> information.originalAmount = typeValue
"SVWZ+" -> details.sepaUsage = typeValue "SVWZ+" -> information.sepaUsage = typeValue
"ABWA+" -> details.deviantOriginator = typeValue "ABWA+" -> information.deviantOriginator = typeValue
"ABWE+" -> details.deviantRecipient = typeValue "ABWE+" -> information.deviantRecipient = typeValue
else -> details.usageWithNoSpecialType = typeValue else -> information.usageWithNoSpecialType = typeValue
} }
} }

View File

@ -1,7 +1,7 @@
package net.dankito.banking.fints.transactions.mt940.model package net.dankito.banking.fints.transactions.mt940.model
open class TransactionDetails( open class InformationToAccountOwner(
val usage: String, val usage: String,
val otherPartyName: String?, val otherPartyName: String?,
val otherPartyBankCode: String?, val otherPartyBankCode: String?,

View File

@ -5,7 +5,7 @@ import java.text.DateFormat
import java.util.* import java.util.*
open class Turnover( open class StatementLine(
/** /**
* Soll/Haben-Kennung * Soll/Haben-Kennung
@ -58,9 +58,11 @@ open class Turnover(
*/ */
val bookingKey: String, val bookingKey: String,
var customerReference: String, val customerReference: String,
var bankReference: String? val bankReference: String?,
val supplementaryDetails: String? = null
) { ) {

View File

@ -3,13 +3,13 @@ package net.dankito.banking.fints.transactions.mt940.model
open class Transaction( open class Transaction(
val turnover: Turnover, val statementLine: StatementLine,
val details: TransactionDetails? = null val information: InformationToAccountOwner? = null
) { ) {
override fun toString(): String { override fun toString(): String {
return "$turnover ($details)" return "$statementLine ($information)"
} }
} }