Implemented mapping all account transaction fields; Renamed usage to unparsedUsage, isCancellation to isReversal, customerReference to referenceForTheAccountOwner, bankReference to referenceOfTheAccountServicingInstitution and referenceReferenceNumber to relatedReferenceNumber

This commit is contained in:
dankito 2020-05-23 19:00:43 +02:00
parent ac78758262
commit a16cf630b4
13 changed files with 228 additions and 171 deletions

View File

@ -6,27 +6,54 @@ import java.util.*
open class AccountTransaction(
val account: AccountData,
val amount: BigDecimal,
val currency: String,
val usage: String,
val isReversal: Boolean,
val unparsedUsage: String,
val bookingDate: Date,
val otherPartyName: String?,
val otherPartyBankCode: String?,
val otherPartyAccountId: String?,
val bookingText: String?,
val valueDate: Date?,
val valueDate: Date,
val statementNumber: Int,
val sequenceNumber: Int?,
val openingBalance: BigDecimal?,
val closingBalance: BigDecimal?,
val account: AccountData
// TODO: may also add other values from parsed usage lines
val endToEndReference: String?,
val customerReference: String?,
val mandateReference: String?,
val creditorIdentifier: String?,
val originatorsIdentificationCode: String?,
val compensationAmount: String?,
val originalAmount: String?,
val sepaUsage: String?,
val deviantOriginator: String?,
val deviantRecipient: String?,
val usageWithNoSpecialType: String?,
val primaNotaNumber: String?,
val textKeySupplement: String?,
val currencyType: String?,
val bookingKey: String,
val referenceForTheAccountOwner: String,
val referenceOfTheAccountServicingInstitution: String?,
val supplementaryDetails: String?,
val transactionReferenceNumber: String,
val relatedReferenceNumber: String?
) {
// for object deserializers
internal constructor() : this(0.toBigDecimal(),"", "", Date(), null, null, null, null, null, null, null, AccountData())
internal constructor() : this(AccountData(), 0.toBigDecimal(),"", false, "", Date(), null, null, null, null, Date(), 0, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null,
null, "", "", null, null, "", null)
override fun toString(): String {
return "${DateFormat.getDateInstance(DateFormat.MEDIUM).format(bookingDate)} $amount $otherPartyName: $usage"
return "${DateFormat.getDateInstance(DateFormat.MEDIUM).format(bookingDate)} $amount $otherPartyName: $unparsedUsage"
}
}

View File

@ -45,18 +45,44 @@ open class Mt940AccountTransactionsParser @JvmOverloads constructor(
protected open fun mapToAccountTransaction(statement: AccountStatement, transaction: Transaction, account: AccountData): AccountTransaction {
return AccountTransaction(
account,
mapAmount(transaction.statementLine),
statement.closingBalance.currency,
transaction.information?.sepaUsage ?: transaction.information?.usage ?: "",
transaction.statementLine.isReversal,
transaction.information?.unparsedUsage ?: "",
transaction.statementLine.bookingDate ?: statement.closingBalance.bookingDate,
transaction.information?.otherPartyName,
transaction.information?.otherPartyBankCode,
transaction.information?.otherPartyAccountId,
transaction.information?.bookingText,
transaction.statementLine.valueDate,
statement.statementNumber,
statement.sequenceNumber,
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
account
transaction.information?.endToEndReference,
transaction.information?.customerReference,
transaction.information?.mandateReference,
transaction.information?.creditorIdentifier,
transaction.information?.originatorsIdentificationCode,
transaction.information?.compensationAmount,
transaction.information?.originalAmount,
transaction.information?.sepaUsage,
transaction.information?.deviantOriginator,
transaction.information?.deviantRecipient,
transaction.information?.usageWithNoSpecialType,
transaction.information?.primaNotaNumber,
transaction.information?.textKeySupplement,
transaction.statementLine.currencyType,
transaction.statementLine.bookingKey,
transaction.statementLine.referenceForTheAccountOwner,
transaction.statementLine.referenceOfTheAccountServicingInstitution,
transaction.statementLine.supplementaryDetails,
statement.transactionReferenceNumber,
statement.relatedReferenceNumber
)
}

View File

@ -57,6 +57,18 @@ open class Mt940Parser : IMt940Parser {
val UsageTypePattern = Pattern.compile("\\w{4}\\+")
const val EndToEndReferenceUsageKey = "EREF+"
const val CustomerReferenceUsageKey = "KREF+"
const val MandateReferenceUsageKey = "MREF+"
const val CreditorIdentifierUsageKey = "CRED+"
const val OriginatorsIdentificationCodeUsageKey = "DEBT+"
const val CompensationAmountUsageKey = "COAM+"
const val OriginalAmountUsageKey = "OAMT+"
const val SepaUsageUsageKey = "SVWZ+"
const val DeviantOriginatorUsageKey = "ABWA+"
const val DeviantRecipientUsageKey = "ABWE+"
private val log = LoggerFactory.getLogger(Mt940Parser::class.java)
}
@ -362,36 +374,35 @@ open class Mt940Parser : IMt940Parser {
* Weitere 4 Verwendungszwecke können zu den Feldschlüsseln 60 bis 63 eingestellt werden.
*/
protected open fun mapUsage(information: InformationToAccountOwner) {
val usageParts = getUsageParts(information)
val usageParts = getUsageParts(information.unparsedUsage)
usageParts.forEach { pair ->
setUsageLineValue(information, pair.first, pair.second)
usageParts.forEach { entry ->
setUsageLineValue(information, entry.key, entry.value)
}
}
protected open fun getUsageParts(information: InformationToAccountOwner): MutableList<Pair<String, String>> {
val usage = information.usage
open fun getUsageParts(unparsedUsage: String): Map<String, String> {
var previousMatchType = ""
var previousMatchEnd = 0
val usageParts = mutableListOf<Pair<String, String>>()
val matcher = UsageTypePattern.matcher(information.usage)
val usageParts = mutableMapOf<String, String>()
val matcher = UsageTypePattern.matcher(unparsedUsage)
while (matcher.find()) {
if (previousMatchEnd > 0) {
val typeValue = usage.substring(previousMatchEnd, matcher.start())
val typeValue = unparsedUsage.substring(previousMatchEnd, matcher.start())
usageParts.add(Pair(previousMatchType, typeValue))
usageParts[previousMatchType] = typeValue
}
previousMatchType = usage.substring(matcher.start(), matcher.end())
previousMatchType = unparsedUsage.substring(matcher.start(), matcher.end())
previousMatchEnd = matcher.end()
}
if (previousMatchEnd > 0) {
val typeValue = usage.substring(previousMatchEnd, usage.length)
val typeValue = unparsedUsage.substring(previousMatchEnd, unparsedUsage.length)
usageParts.add(Pair(previousMatchType, typeValue))
usageParts[previousMatchType] = typeValue
}
return usageParts
@ -399,16 +410,16 @@ open class Mt940Parser : IMt940Parser {
protected open fun setUsageLineValue(information: InformationToAccountOwner, usageType: String, typeValue: String) {
when (usageType) {
"EREF+" -> information.endToEndReference = typeValue
"KREF+" -> information.customerReference = typeValue
"MREF+" -> information.mandateReference = typeValue
"CRED+" -> information.creditorIdentifier = typeValue
"DEBT+" -> information.originatorsIdentificationCode = typeValue
"COAM+" -> information.compensationAmount = typeValue
"OAMT+" -> information.originalAmount = typeValue
"SVWZ+" -> information.sepaUsage = typeValue
"ABWA+" -> information.deviantOriginator = typeValue
"ABWE+" -> information.deviantRecipient = typeValue
EndToEndReferenceUsageKey -> information.endToEndReference = typeValue
CustomerReferenceUsageKey -> information.customerReference = typeValue
MandateReferenceUsageKey -> information.mandateReference = typeValue
CreditorIdentifierUsageKey -> information.creditorIdentifier = typeValue
OriginatorsIdentificationCodeUsageKey -> information.originatorsIdentificationCode = typeValue
CompensationAmountUsageKey -> information.compensationAmount = typeValue
OriginalAmountUsageKey -> information.originalAmount = typeValue
SepaUsageUsageKey -> information.sepaUsage = typeValue
DeviantOriginatorUsageKey -> information.deviantOriginator = typeValue
DeviantRecipientUsageKey -> information.deviantRecipient = typeValue
else -> information.usageWithNoSpecialType = typeValue
}
}

View File

@ -20,7 +20,7 @@ open class AccountStatement(
*
* Max length = 16
*/
val referenceReferenceNumber: String?,
val relatedReferenceNumber: String?,
/**
* xxxxxxxxxxx/Konto-Nr. oder yyyyyyyy/Konto-Nr.

View File

@ -2,7 +2,7 @@ package net.dankito.banking.fints.transactions.mt940.model
open class InformationToAccountOwner(
val usage: String,
val unparsedUsage: String,
val otherPartyName: String?,
val otherPartyBankCode: String?,
val otherPartyAccountId: String?,
@ -35,7 +35,7 @@ open class InformationToAccountOwner(
override fun toString(): String {
return "$otherPartyName $usage"
return "$otherPartyName $unparsedUsage"
}
}

View File

@ -19,7 +19,7 @@ open class StatementLine(
*/
val isCredit: Boolean,
val isCancellation: Boolean,
val isReversal: Boolean,
/**
* Valuta (JJMMTT)
@ -58,9 +58,9 @@ open class StatementLine(
*/
val bookingKey: String,
val customerReference: String,
val referenceForTheAccountOwner: String,
val bankReference: String?,
val referenceOfTheAccountServicingInstitution: String?,
val supplementaryDetails: String? = null

View File

@ -249,7 +249,7 @@ class Mt940ParserTest : FinTsTestBase() {
bookingDate: Date? = valueDate) {
assertThat(statementLine.isCredit).isEqualTo(isCredit)
assertThat(statementLine.isCancellation).isFalse()
assertThat(statementLine.isReversal).isFalse()
assertThat(statementLine.valueDate).isEqualTo(valueDate)
assertThat(statementLine.bookingDate).isEqualTo(bookingDate)
assertThat(statementLine.amount).isEqualTo(amount)

View File

@ -72,9 +72,9 @@ open class LuceneBankingPersistence(
fields.storedField(BookingDateFieldName, transaction.bookingDate),
fields.storedField(AmountFieldName, transaction.amount),
fields.storedField(CurrencyFieldName, transaction.currency),
fields.nullableStoredField(BalanceFieldName, transaction.balance),
fields.nullableStoredField(BalanceFieldName, transaction.closingBalance), // TODO: remove
fields.sortField(BookingDateSortFieldName, transaction.bookingDate)
fields.sortField(BookingDateSortFieldName, transaction.bookingDate) // TODO: sort by valueDate
)
}

View File

@ -211,7 +211,7 @@ class LuceneRemitteeSearcherTest {
otherPartyName: String = randomString(), otherPartyBankCode: String = randomString(),
otherPartyAccountId: String = randomString(), usage: String = randomString()): AccountTransaction {
return AccountTransaction(amount, bookingDate, usage, otherPartyName, otherPartyBankCode, otherPartyAccountId, null, null, "EUR", bankAccount)
return AccountTransaction(bankAccount, amount, usage, bookingDate, otherPartyName, otherPartyBankCode, otherPartyAccountId, null, bookingDate)
}
private fun randomString(): String {

View File

@ -72,7 +72,7 @@ open class AccountTransactionsTable @JvmOverloads constructor(
}
}
label(it.usage ?: "") {
label(it.usage) {
vboxConstraints {
margin = LabelMargin
}

View File

@ -9,20 +9,57 @@ import java.util.*
@JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references
open class AccountTransaction(
val bankAccount: BankAccount,
val amount: BigDecimal,
val currency: String,
val isReversal: Boolean,
val unparsedUsage: String,
val bookingDate: Date,
val usage: String,
val otherPartyName: String?,
val otherPartyBankCode: String?,
val otherPartyAccountId: String?,
val bookingText: String?,
val balance: BigDecimal?,
val currency: String,
val bankAccount: BankAccount
val valueDate: Date,
val statementNumber: Int,
val sequenceNumber: Int?,
val openingBalance: BigDecimal?,
val closingBalance: BigDecimal?,
val endToEndReference: String?,
val customerReference: String?,
val mandateReference: String?,
val creditorIdentifier: String?,
val originatorsIdentificationCode: String?,
val compensationAmount: String?,
val originalAmount: String?,
val sepaUsage: String?,
val deviantOriginator: String?,
val deviantRecipient: String?,
val usageWithNoSpecialType: String?,
val primaNotaNumber: String?,
val textKeySupplement: String?,
val currencyType: String?,
val bookingKey: String,
val referenceForTheAccountOwner: String,
val referenceOfTheAccountServicingInstitution: String?,
val supplementaryDetails: String?,
val transactionReferenceNumber: String,
val relatedReferenceNumber: String?
) {
constructor(bankAccount: BankAccount, amount: BigDecimal, unparsedUsage: String, bookingDate: Date,
otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?,
bookingText: String?, valueDate: Date)
: this(bankAccount, amount, "EUR", false, unparsedUsage, bookingDate,
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)
// for object deserializers
internal constructor() : this(BigDecimal.ZERO, Date(),"", null, null, null, null, BigDecimal.ZERO, "", BankAccount())
internal constructor() : this(BankAccount(), BigDecimal.ZERO, "", false,"", Date(), null, null, null, null, Date(), 0, null, BigDecimal.ZERO, BigDecimal.ZERO,
null, null, null, null, null, null, null, null, null, null, null, null, null,
null, "", "", null, null, "", null)
var id: String = UUID.randomUUID().toString()
@ -32,6 +69,9 @@ open class AccountTransaction(
val showOtherPartyName: Boolean
get() = otherPartyName.isNullOrBlank() == false /* && type != "ENTGELTABSCHLUSS" && type != "AUSZAHLUNG" */ // TODO
val usage: String
get() = sepaUsage ?: unparsedUsage
override fun equals(other: Any?): Boolean {
if (this === other) return true
@ -39,7 +79,7 @@ open class AccountTransaction(
if (amount.compareTo(other.amount) != 0) return false
if (currency != other.currency) return false
if (usage != other.usage) return false
if (unparsedUsage != other.unparsedUsage) return false
if (bookingDate != other.bookingDate) return false
if (otherPartyName != other.otherPartyName) return false
if (otherPartyBankCode != other.otherPartyBankCode) return false
@ -53,7 +93,7 @@ open class AccountTransaction(
override fun hashCode(): Int {
var result = amount.hashCode()
result = 31 * result + currency.hashCode()
result = 31 * result + usage.hashCode()
result = 31 * result + unparsedUsage.hashCode()
result = 31 * result + bookingDate.hashCode()
result = 31 * result + (otherPartyName?.hashCode() ?: 0)
result = 31 * result + (otherPartyBankCode?.hashCode() ?: 0)

View File

@ -175,16 +175,44 @@ open class fints4kModelMapper {
open fun mapTransaction(bankAccount: BankAccount, transaction: net.dankito.banking.fints.model.AccountTransaction): AccountTransaction {
return AccountTransaction(
bankAccount,
transaction.amount,
transaction.currency,
transaction.isReversal,
transaction.unparsedUsage,
transaction.bookingDate,
transaction.usage,
transaction.otherPartyName,
transaction.otherPartyBankCode,
transaction.otherPartyAccountId,
transaction.bookingText,
transaction.valueDate,
transaction.statementNumber,
transaction.sequenceNumber,
transaction.openingBalance,
transaction.closingBalance,
transaction.currency,
bankAccount
transaction.endToEndReference,
transaction.customerReference,
transaction.mandateReference,
transaction.creditorIdentifier,
transaction.originatorsIdentificationCode,
transaction.compensationAmount,
transaction.originalAmount,
transaction.sepaUsage,
transaction.deviantOriginator,
transaction.deviantRecipient,
transaction.usageWithNoSpecialType,
transaction.primaNotaNumber,
transaction.textKeySupplement,
transaction.currencyType,
transaction.bookingKey,
transaction.referenceForTheAccountOwner,
transaction.referenceOfTheAccountServicingInstitution,
transaction.supplementaryDetails,
transaction.transactionReferenceNumber,
transaction.relatedReferenceNumber
)
}

View File

@ -1,8 +1,10 @@
package net.dankito.banking.util
import net.dankito.banking.fints.transactions.mt940.Mt940Parser
import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount
import org.kapott.hbci.GV_Result.GVRKUms
import org.kapott.hbci.structures.Value
import org.slf4j.LoggerFactory
import java.math.BigDecimal
import java.text.SimpleDateFormat
@ -25,8 +27,10 @@ open class AccountTransactionMapper {
open fun mapAccountTransactions(bankAccount: BankAccount, result: GVRKUms): List<AccountTransaction> {
val entries = ArrayList<AccountTransaction>()
result.flatData.forEach { transaction ->
entries.add(mapAccountingEntry(bankAccount, transaction))
result.dataPerDay.forEach { btag ->
btag.lines.forEach { transaction ->
entries.add(mapAccountingEntry(bankAccount, btag, transaction))
}
}
log.debug("Retrieved ${result.flatData.size} accounting entries")
@ -34,129 +38,50 @@ open class AccountTransactionMapper {
return entries.sortedByDescending { it.bookingDate }
}
protected open fun mapAccountingEntry(bankAccount: BankAccount, transaction: GVRKUms.UmsLine): AccountTransaction {
protected open fun mapAccountingEntry(bankAccount: BankAccount, btag: GVRKUms.BTag, transaction: GVRKUms.UmsLine): AccountTransaction {
val unparsedUsage = transaction.usage.joinToString("")
val parsedUsage = Mt940Parser().getUsageParts(unparsedUsage)
val statementAndMaySequenceNumber = btag.counter.split('/')
val result = AccountTransaction(BigDecimal.valueOf(transaction.value.longValue).divide(BigDecimal.valueOf(100)), transaction.bdate, transaction.usage.joinToString(""),
if (transaction.other.name2.isNullOrBlank() == false) transaction.other.name + " " + transaction.other.name2 else transaction.other.name,
if (transaction.other.bic != null) transaction.other.bic else transaction.other.blz,
if (transaction.other.iban != null) transaction.other.iban else transaction.other.number,
transaction.text, BigDecimal.valueOf(transaction.saldo.value.longValue), transaction.value.curr, bankAccount)
val result = AccountTransaction(bankAccount,
mapValue(transaction.value), transaction.value.curr, transaction.isStorno, unparsedUsage, transaction.bdate,
transaction.other.name + (transaction.other.name2 ?: ""),
transaction.other.bic ?: transaction.other.blz,
transaction.other.iban ?: transaction.other.number,
transaction.text, transaction.valuta,
statementAndMaySequenceNumber[0].toInt(),
if (statementAndMaySequenceNumber.size > 1) statementAndMaySequenceNumber[1].toInt() else null,
mapValue(btag.start.value), mapValue(btag.end.value),
// mapUsage(transaction, result)
parsedUsage[Mt940Parser.EndToEndReferenceUsageKey],
parsedUsage[Mt940Parser.CustomerReferenceUsageKey],
parsedUsage[Mt940Parser.MandateReferenceUsageKey],
parsedUsage[Mt940Parser.CreditorIdentifierUsageKey],
parsedUsage[Mt940Parser.OriginatorsIdentificationCodeUsageKey],
parsedUsage[Mt940Parser.CompensationAmountUsageKey],
parsedUsage[Mt940Parser.OriginalAmountUsageKey],
parsedUsage[Mt940Parser.SepaUsageUsageKey],
parsedUsage[Mt940Parser.DeviantOriginatorUsageKey],
parsedUsage[Mt940Parser.DeviantRecipientUsageKey],
parsedUsage[""],
transaction.primanota,
transaction.addkey,
null,
"",
transaction.customerref,
transaction.instref,
transaction.additional,
"",
null
)
return result
}
/**
* From https://sites.google.com/a/crem-solutions.de/doku/version-2012-neu/buchhaltung/03-zahlungsverkehr/05-e-banking/technische-beschreibung-der-mt940-sta-datei:
*
* Weitere 4 Verwendungszwecke können zu den Feldschlüsseln 60 bis 63 eingestellt werden.
* Jeder Bezeichner [z.B. EREF+] muss am Anfang eines Subfeldes [z. B. ?21] stehen.
* Bei Längenüberschreitung wird im nachfolgenden Subfeld ohne Wiederholung des Bezeichners fortgesetzt. Bei Wechsel des Bezeichners ist ein neues Subfeld zu beginnen.
* Belegung in der nachfolgenden Reihenfolge, wenn vorhanden:
* EREF+[ Ende-zu-Ende Referenz ] (DD-AT10; CT-AT41 - Angabe verpflichtend; NOTPROVIDED wird nicht eingestellt.)
* KREF+[Kundenreferenz]
* MREF+[Mandatsreferenz] (DD-AT01 - Angabe verpflichtend)
* CRED+[Creditor Identifier] (DD-AT02 - Angabe verpflichtend bei SEPA-Lastschriften, nicht jedoch bei SEPA-Rücklastschriften)
* DEBT+[Originators Identification Code](CT-AT10- Angabe verpflichtend,)
* Entweder CRED oder DEBT
*
* optional zusätzlich zur Einstellung in Feld 61, Subfeld 9:
*
* COAM+ [Compensation Amount / Summe aus Auslagenersatz und Bearbeitungsprovision bei einer nationalen Rücklastschrift sowie optionalem Zinsausgleich.]
* OAMT+[Original Amount] Betrag der ursprünglichen Lastschrift
*
* SVWZ+[SEPA-Verwendungszweck] (DD-AT22; CT-AT05 -Angabe verpflichtend, nicht jedoch bei R-Transaktionen)
* ABWA+[Abweichender Überweisender] (CT-AT08) / Abweichender Zahlungsempfänger (DD-AT38) ] (optional)
* ABWE+[Abweichender Zahlungsemp-fänger (CT-AT28) / Abweichender Zahlungspflichtiger ((DD-AT15)] (optional)
*/
// protected open fun mapUsage(buchung: GVRKUms.UmsLine, entry: AccountingEntry) {
// var lastUsageLineType = UsageLineType.ContinuationFromLastLine
// var typeValue = ""
//
// buchung.usage.forEach { line ->
// val (type, adjustedString) = getUsageLineType(line, entry)
//
// if (type == UsageLineType.ContinuationFromLastLine) {
// typeValue += (if(adjustedString[0].isUpperCase()) " " else "") + adjustedString
// }
// else if (lastUsageLineType != type) {
// if (lastUsageLineType != UsageLineType.ContinuationFromLastLine) {
// setUsageLineValue(entry, lastUsageLineType, typeValue)
// }
//
// typeValue = adjustedString
// lastUsageLineType = type
// }
//
// tryToParseBookingDateFromUsageLine(entry, adjustedString, typeValue)
// }
//
// if(lastUsageLineType != UsageLineType.ContinuationFromLastLine) {
// setUsageLineValue(entry, lastUsageLineType, typeValue)
// }
// }
//
// protected open fun setUsageLineValue(entry: AccountingEntry, lastUsageLineType: UsageLineType, typeValue: String) {
// entry.parsedUsages.add(typeValue)
//
// when (lastUsageLineType) {
// UsageLineType.EREF -> entry.endToEndReference = typeValue
// UsageLineType.KREF -> entry.kundenreferenz = typeValue
// UsageLineType.MREF -> entry.mandatsreferenz = typeValue
// UsageLineType.CRED -> entry.creditorIdentifier = typeValue
// UsageLineType.DEBT -> entry.originatorsIdentificationCode = typeValue
// UsageLineType.COAM -> entry.compensationAmount = typeValue
// UsageLineType.OAMT -> entry.originalAmount = typeValue
// UsageLineType.SVWZ -> entry.sepaVerwendungszweck = typeValue
// UsageLineType.ABWA -> entry.abweichenderAuftraggeber = typeValue
// UsageLineType.ABWE -> entry.abweichenderZahlungsempfaenger = typeValue
// UsageLineType.NoSpecialType -> entry.usageWithNoSpecialType = typeValue
// }
// }
//
// protected open fun getUsageLineType(line: String, entry: AccountingEntry): Pair<UsageLineType, String> {
// return when {
// line.startsWith("EREF+") -> Pair(UsageLineType.EREF, line.substring(5))
// line.startsWith("KREF+") -> Pair(UsageLineType.KREF, line.substring(5))
// line.startsWith("MREF+") -> Pair(UsageLineType.MREF, line.substring(5))
// line.startsWith("CRED+") -> Pair(UsageLineType.CRED, line.substring(5))
// line.startsWith("DEBT+") -> Pair(UsageLineType.DEBT, line.substring(5))
// line.startsWith("COAM+") -> Pair(UsageLineType.COAM, line.substring(5))
// line.startsWith("OAMT+") -> Pair(UsageLineType.OAMT, line.substring(5))
// line.startsWith("SVWZ+") -> Pair(UsageLineType.SVWZ, line.substring(5))
// line.startsWith("ABWA+") -> Pair(UsageLineType.ABWA, line.substring(5))
// line.startsWith("ABWE+") -> Pair(UsageLineType.ABWE, line.substring(5))
// entry.usage.startsWith(line) -> Pair(UsageLineType.NoSpecialType, line)
// else -> Pair(UsageLineType.ContinuationFromLastLine, line)
// }
// }
//
// protected open fun tryToParseBookingDateFromUsageLine(entry: AccountingEntry, currentLine: String, typeLine: String) {
// if (currentLine.startsWith(DateStartString)) {
// tryToParseBookingDateFromUsageLine(entry, currentLine)
// }
// else if (typeLine.startsWith(DateStartString)) {
// tryToParseBookingDateFromUsageLine(entry, typeLine)
// }
// }
//
// protected open fun tryToParseBookingDateFromUsageLine(entry: AccountingEntry, line: String) {
// var dateString = line.replace(DateStartString, "")
// val index = dateString.indexOf(DateEndString)
// if (index > 0) {
// dateString = dateString.substring(0, index)
// }
//
// try {
// entry.bookingDate = DateTimeFormat.parse(dateString)
// } catch (e: Exception) {
// try {
// entry.bookingDate = DateFormat.parse(dateString)
// } catch (secondException: Exception) {
// log.debug("Could not parse '$dateString' from '$line' to a Date", e)
// }
// }
// }
protected open fun mapValue(value: Value): BigDecimal {
return BigDecimal.valueOf(value.longValue).divide(BigDecimal.valueOf(100))
}
}