diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt index f7a5435f..69e3ba91 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/FinTsClient.kt @@ -3,6 +3,7 @@ package net.dankito.banking.fints import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import net.dankito.banking.fints.callback.FinTsClientCallback +import net.dankito.banking.fints.log.IMessageLogAppender import net.dankito.banking.fints.log.MessageLogCollector import net.dankito.banking.fints.messages.MessageBuilder import net.dankito.banking.fints.messages.MessageBuilderResult @@ -68,6 +69,12 @@ open class FinTsClient( } + init { + responseParser.logAppender = messageLogAppender + mt940Parser.logAppender = messageLogAppender + } + + /** * Retrieves information about bank (e.g. supported HBCI versions, FinTS server address, * supported jobs, ...). @@ -394,7 +401,8 @@ open class FinTsClient( dialogContext.chunkedResponseHandler = { response -> response.getFirstSegmentById(InstituteSegmentId.AccountTransactionsMt940)?.let { transactionsSegment -> - val (chunkTransaction, remainder) = mt940Parser.parseTransactionsChunk(remainingMt940String + transactionsSegment.bookedTransactionsString, parameter.account) + val (chunkTransaction, remainder) = mt940Parser.parseTransactionsChunk(remainingMt940String + transactionsSegment.bookedTransactionsString, + dialogContext.bank, parameter.account) bookedTransactions.addAll(chunkTransaction) remainingMt940String = remainder diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/log/IMessageLogAppender.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/log/IMessageLogAppender.kt new file mode 100644 index 00000000..c30c28e0 --- /dev/null +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/log/IMessageLogAppender.kt @@ -0,0 +1,11 @@ +package net.dankito.banking.fints.log + +import net.dankito.banking.fints.model.BankData +import net.dankito.utils.multiplatform.log.Logger + + +interface IMessageLogAppender { + + fun logError(message: String, e: Exception? = null, logger: Logger? = null, bank: BankData? = null) + +} \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/ResponseParser.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/ResponseParser.kt index 68afb1a2..b537362d 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/ResponseParser.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/response/ResponseParser.kt @@ -1,5 +1,6 @@ package net.dankito.banking.fints.response +import net.dankito.banking.fints.log.IMessageLogAppender import net.dankito.banking.fints.messages.Separators import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Datum import net.dankito.banking.fints.messages.datenelemente.abgeleiteteformate.Uhrzeit @@ -25,7 +26,8 @@ import net.dankito.utils.multiplatform.log.LoggerFactory open class ResponseParser( - protected val messageUtils: MessageUtils = MessageUtils() + protected open val messageUtils: MessageUtils = MessageUtils(), + open var logAppender: IMessageLogAppender? = null ) { companion object { @@ -52,7 +54,7 @@ open class ResponseParser( return BankResponse(true, response, parsedSegments) } catch (e: Exception) { - log.error(e) { "Could not parse response '$response'" } + logError("Could not parse response '$response'", e) return BankResponse(true, response, errorMessage = e.getInnerExceptionMessage()) } @@ -84,7 +86,7 @@ open class ResponseParser( return parseSegment(segment, segmentId, dataElementGroups) } } catch (e: Exception) { - log.error(e) { "Could not parse segment '$segment'" } // TODO: what to do here, how to inform user? + logError("Could not parse segment '$segment'", e) // TODO: what to do here, how to inform user? } return null @@ -463,7 +465,7 @@ open class ResponseParser( return parseCodeEnum(smsAbbuchungskontoErforderlichString, SmsAbbuchungskontoErforderlich.values()) } catch (e: Exception) { if (isEncodedBooleanValue(smsAbbuchungskontoErforderlichString) == false) { - log.error(e) { "Could not parse '$smsAbbuchungskontoErforderlichString' to SmsAbbuchungskontoErforderlich" } + logError("Could not parse '$smsAbbuchungskontoErforderlichString' to SmsAbbuchungskontoErforderlich", e) } } @@ -478,7 +480,7 @@ open class ResponseParser( return parseCodeEnum(auftraggeberkontoErforderlichString, AuftraggeberkontoErforderlich.values()) } catch (e: Exception) { if (isEncodedBooleanValue(auftraggeberkontoErforderlichString) == false) { - log.error(e) { "Could not parse '$auftraggeberkontoErforderlichString' to AuftraggeberkontoErforderlich" } + logError("Could not parse '$auftraggeberkontoErforderlichString' to AuftraggeberkontoErforderlich", e) } } @@ -708,7 +710,7 @@ open class ResponseParser( return CreditCardTransaction(amount, transactionDescriptionBase, transactionDescriptionSupplement, bookingDate, valueDate, isCleared) } catch (e: Exception) { - log.error("Could not parse Credit card transaction '$transactionDataElementGroup'", e) + logError("Could not parse Credit card transaction '$transactionDataElementGroup'", e) } return null @@ -978,4 +980,14 @@ open class ResponseParser( return binaryData } + + protected open fun logError(message: String, e: Exception?) { + logAppender?.let { logAppender -> + logAppender.logError(message, e, log) + } + ?: run { + log.error(e) { message } + } + } + } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/IAccountTransactionsParser.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/IAccountTransactionsParser.kt index 83e6fabc..3558e3fd 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/IAccountTransactionsParser.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/IAccountTransactionsParser.kt @@ -1,13 +1,18 @@ package net.dankito.banking.fints.transactions +import net.dankito.banking.fints.log.IMessageLogAppender import net.dankito.banking.fints.model.AccountData import net.dankito.banking.fints.model.AccountTransaction +import net.dankito.banking.fints.model.BankData interface IAccountTransactionsParser { - fun parseTransactions(transactionsString: String, account: AccountData): List + var logAppender: IMessageLogAppender? - fun parseTransactionsChunk(transactionsChunk: String, account: AccountData): Pair, String> + + fun parseTransactions(transactionsString: String, bank: BankData, account: AccountData): List + + fun parseTransactionsChunk(transactionsChunk: String, bank: BankData, account: AccountData): Pair, String> } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParser.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParser.kt index 419fee0b..847795e5 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParser.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParser.kt @@ -1,9 +1,7 @@ package net.dankito.banking.fints.transactions -import net.dankito.banking.fints.model.AccountData -import net.dankito.banking.fints.model.AccountTransaction -import net.dankito.banking.fints.model.Amount -import net.dankito.banking.fints.model.Money +import net.dankito.banking.fints.log.IMessageLogAppender +import net.dankito.banking.fints.model.* import net.dankito.banking.fints.transactions.mt940.IMt940Parser import net.dankito.banking.fints.transactions.mt940.Mt940Parser import net.dankito.banking.fints.transactions.mt940.model.AccountStatement @@ -11,10 +9,12 @@ 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.StatementLine import net.dankito.utils.multiplatform.log.LoggerFactory +import net.dankito.utils.multiplatform.log.Logger open class Mt940AccountTransactionsParser( - protected val mt940Parser: IMt940Parser = Mt940Parser() + protected val mt940Parser: IMt940Parser = Mt940Parser(), + override var logAppender: IMessageLogAppender? = null ) : IAccountTransactionsParser { companion object { @@ -22,23 +22,25 @@ open class Mt940AccountTransactionsParser( } - override fun parseTransactions(transactionsString: String, account: AccountData): List { + override fun parseTransactions(transactionsString: String, bank: BankData, account: AccountData): List { + setLogAppender(bank) + val accountStatements = mt940Parser.parseMt940String(transactionsString) - return accountStatements.flatMap { mapToAccountTransactions(it, account) } + return accountStatements.flatMap { mapToAccountTransactions(it, bank, account) } } - override fun parseTransactionsChunk(transactionsChunk: String, account: AccountData): Pair, String> { + override fun parseTransactionsChunk(transactionsChunk: String, bank: BankData, account: AccountData): Pair, String> { val (accountStatements, remainder) = mt940Parser.parseMt940Chunk(transactionsChunk) - return Pair(accountStatements.flatMap { mapToAccountTransactions(it, account) }, remainder) + return Pair(accountStatements.flatMap { mapToAccountTransactions(it, bank, account) }, remainder) } - protected open fun mapToAccountTransactions(statement: AccountStatement, account: AccountData): List { + protected open fun mapToAccountTransactions(statement: AccountStatement, bank: BankData, account: AccountData): List { try { return statement.transactions.map { mapToAccountTransaction(statement, it, account) } } catch (e: Exception) { - log.error(e) { "Could not map AccountStatement '$statement' to AccountTransactions" } + logError("Could not map AccountStatement '$statement' to AccountTransactions", e, bank) } return listOf() @@ -113,4 +115,27 @@ open class Mt940AccountTransactionsParser( return positiveAmount } + + protected open fun setLogAppender(bankDataOfCall: BankData) { + // TODO: this does not perfectly work as in parallel calls to Mt940AccountTransactionsParser for different account logAppender gets overwritten by the later call + mt940Parser.logAppender = logAppender?.let { logAppender -> + object : IMessageLogAppender { + + override fun logError(message: String, e: Exception?, logger: Logger?, bank: BankData?) { + logAppender.logError(message, e, logger, bank ?: bankDataOfCall) + } + + } + } + } + + protected open fun logError(message: String, e: Exception?, bank: BankData) { + logAppender?.let { logAppender -> + logAppender.logError(message, e, log, bank) + } + ?: run { + log.error(e) { message } + } + } + } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/IMt940Parser.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/IMt940Parser.kt index 7b5d8a20..d31784e9 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/IMt940Parser.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/IMt940Parser.kt @@ -1,10 +1,14 @@ package net.dankito.banking.fints.transactions.mt940 +import net.dankito.banking.fints.log.IMessageLogAppender import net.dankito.banking.fints.transactions.mt940.model.AccountStatement interface IMt940Parser { + var logAppender: IMessageLogAppender? + + /** * Parses a whole MT 940 statements string, that is one that ends with a "-" line. */ diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/Mt940Parser.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/Mt940Parser.kt index 24aa3a3e..1541b35f 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/Mt940Parser.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/transactions/mt940/Mt940Parser.kt @@ -1,5 +1,6 @@ package net.dankito.banking.fints.transactions.mt940 +import net.dankito.banking.fints.log.IMessageLogAppender import net.dankito.banking.fints.model.Amount import net.dankito.banking.fints.transactions.mt940.model.* import net.dankito.utils.multiplatform.Date @@ -77,6 +78,9 @@ open class Mt940Parser : IMt940Parser { } + override var logAppender: IMessageLogAppender? = null + + /** * Parses a whole MT 940 statements string, that is one that ends with a "-" line. */ @@ -108,7 +112,7 @@ open class Mt940Parser : IMt940Parser { return Pair(transactions, remainder) } catch (e: Exception) { - log.error(e) { "Could not parse account statements from MT940 string:\n$mt940Chunk" } + logError("Could not parse account statements from MT940 string:\n$mt940Chunk", e) } return Pair(listOf(), "") @@ -131,7 +135,7 @@ open class Mt940Parser : IMt940Parser { return parseAccountStatement(fieldsByCode) } catch (e: Exception) { - log.error(e) { "Could not parse account statement:\n$accountStatementString" } + logError("Could not parse account statement:\n$accountStatementString", e) } return null @@ -301,7 +305,7 @@ open class Mt940Parser : IMt940Parser { return information } catch (e: Exception) { - log.error(e) { "Could not parse InformationToAccountOwner from field value '$informationToAccountOwnerString'" } + logError("Could not parse InformationToAccountOwner from field value '$informationToAccountOwnerString'", e) } return null @@ -463,7 +467,7 @@ open class Mt940Parser : IMt940Parser { return Date(year + 2000, month, day) // java.util.Date years start at 1900 at month at 0 not at 1 } catch (e: Exception) { - log.error(e) { "Could not parse dateString '$dateString'" } + logError("Could not parse dateString '$dateString'", e) } } @@ -489,4 +493,14 @@ open class Mt940Parser : IMt940Parser { return Amount(amountString) } + + protected open fun logError(message: String, e: Exception?) { + logAppender?.let { logAppender -> + logAppender.logError(message, e, log) + } + ?: run { + log.error(e) { message } + } + } + } \ No newline at end of file diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt index a92b7fe2..5586cbe0 100644 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt +++ b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt @@ -2,6 +2,7 @@ package net.dankito.banking.fints.transactions import net.dankito.banking.fints.FinTsTestBaseJvm import net.dankito.banking.fints.model.AccountData +import net.dankito.banking.fints.model.BankData import org.assertj.core.api.Assertions.assertThat import org.junit.Test @@ -20,7 +21,7 @@ class Mt940AccountTransactionsParserTest : FinTsTestBaseJvm() { // when - val result = underTest.parseTransactions(transactionsString, AccountData()) + val result = underTest.parseTransactions(transactionsString, BankData(), AccountData()) // then