libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit e3b58a2ca0b59045d2c5d754828be78eef9ce883
parent 65dd58fc819562255679db601b950044732a3a79
Author: Florian Dold <florian.dold@gmail.com>
Date:   Thu, 11 Jun 2020 23:04:14 +0530

further camt parsing improvements

Diffstat:
Mnexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt | 56++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mutil/src/main/kotlin/XmlCombinators.kt | 1-
2 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt @@ -36,6 +36,19 @@ enum class TransactionStatus { BOOK, PENDING } +/** + * Schemes to identify a transaction within an account. + * An identifier from such a scheme will be used to reconcile transactions + * from multiple sources. + * (LibEuFin-specific, not defined by ISO 20022) + */ +enum class TransactionIdentifierSchemes { + /** + * Reconcile based on the account servicer reference. + */ + AcctSvcrRef +} + data class TransactionDetails( /** * Related parties as JSON. @@ -53,9 +66,14 @@ data class TransactionDetails( data class BankTransaction( val accountIdentifier: String, /** + * Identifier for the transaction that should be unique within an account. + * Prefix by the identifier scheme name followed by a colon. + */ + val transactionIdentifier: String, + /** * Scheme used for the account identifier. */ - val accountScheme: String, + val accountIdentifierScheme: String, val currency: String, val amount: String, /** @@ -76,7 +94,10 @@ data class BankTransaction( * Is this a batch booking? */ val isBatch: Boolean, - val details: List<TransactionDetails> + val details: List<TransactionDetails>, + val valueDate: DateOrDateTime?, + val bookingDate: DateOrDateTime?, + val accountServicerReference: String ) abstract class TypedEntity(val type: String) @@ -97,6 +118,16 @@ class Account( val iban: String? ) : TypedEntity("party") +abstract class DateOrDateTime(type: String) : TypedEntity(type) + +class Date( + val date: String +) : DateOrDateTime("date") + +class DateTime( + val date: String +) : DateOrDateTime("datetime") + @JsonInclude(JsonInclude.Include.NON_NULL) data class BankTransactionCode( @@ -143,6 +174,16 @@ data class RelatedParties( class CamtParsingError(msg: String) : Exception(msg) +private fun XmlElementDestructor.extractDateOrDateTime(): DateOrDateTime { + return requireOnlyChild { + when (it.localName) { + "Dt" -> Date(e.textContent) + "DtTm" -> DateTime(e.textContent) + else -> throw Exception("Invalid date / time: ${e.localName}") + } + } +} + private fun XmlElementDestructor.extractAgent(): Agent { return Agent( name = maybeUniqueChildNamed("FinInstnId") { @@ -277,17 +318,24 @@ private fun XmlElementDestructor.extractInnerTransactions(): List<BankTransactio } ) } + val acctSvcrRef = maybeUniqueChildNamed("AcctSvcrRef") { it.textContent } + // For now, only support account servicer reference as id + val txId = "AcctSvcrRef:" + (acctSvcrRef ?: throw Exception("currently, AcctSvcrRef is mandatory in LibEuFin")) val details = extractTransactionDetails() BankTransaction( accountIdentifier = iban, - accountScheme = "iban", + accountIdentifierScheme = "iban", amount = amount, currency = currency, status = status, creditDebitIndicator = creditDebitIndicator, bankTransactionCode = btc, details = details, - isBatch = details.size > 1 + isBatch = details.size > 1, + bookingDate = maybeUniqueChildNamed("BookgDt") { extractDateOrDateTime() }, + valueDate = maybeUniqueChildNamed("ValDt") { extractDateOrDateTime() }, + accountServicerReference = acctSvcrRef, + transactionIdentifier = txId ) } } diff --git a/util/src/main/kotlin/XmlCombinators.kt b/util/src/main/kotlin/XmlCombinators.kt @@ -145,7 +145,6 @@ class XmlElementDestructor internal constructor(val d: Document, val e: Element) if (cl.size == 1) { val el = cl[0] val destr = XmlElementDestructor(d, el) - println("found child $s") return f(destr, el) } return null