libeufin

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

commit 570cd2cd8bfbaf946756ac91ac7aaee73818b487
parent 011160577a53e1e8878346ef4771ceb939feb588
Author: MS <ms@taler.net>
Date:   Wed,  1 Sep 2021 10:25:23 +0000

Camt timestamping uses UTC.

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 18++++++++++++------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 5+++--
Mutil/src/main/kotlin/time.kt | 24+++++++++++++-----------
3 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -230,10 +230,12 @@ fun buildCamtString( * - Proprietary code of the bank transaction * - Id of the servicer (Issuer and Code) */ - val creationTime = LocalDateTime.now() + val creationTime = getUTCnow() val dashedDate = creationTime.toDashedDate() val zonedDateTime = creationTime.toZonedString() - val messageId = "sandbox-${creationTime.millis()}" + val creationTimeMillis = creationTime.toInstant().toEpochMilli() + val messageId = "sandbox-${creationTimeMillis}" + val camtMessage = constructXml(indent = true) { root("Document") { attribute("xmlns", "urn:iso:std:iso:20022:tech:xsd:camt.0${type}.001.02") @@ -457,11 +459,11 @@ fun buildCamtString( return SandboxCamt( camtMessage = camtMessage, messageId = messageId, - creationTime = creationTime.millis() + creationTime = creationTimeMillis ) } -fun getHistoryElementFromDbRow( +fun getHistoryElementFromTransactionRow( dbRow: BankAccountFreshTransactionEntity ): RawPayment { return RawPayment( @@ -518,7 +520,7 @@ private fun constructCamtResponse( val lastBalance = transaction { BankAccountFreshTransactionEntity.all().forEach { if (it.transactionRef.account.label == bankAccount.label) { - history.add(getHistoryElementFromDbRow(it)) + history.add(getHistoryElementFromTransactionRow(it)) } } getLastBalance(bankAccount) // last reported balance @@ -537,6 +539,8 @@ private fun constructCamtResponse( ).camtMessage ) } + SandboxAssert(type == 53, "Didn't catch unsupported Camt type") + logger.debug("Finding C$type records") /** * FIXME: when this function throws an exception, it makes a JSON response being responded. @@ -550,6 +554,7 @@ private fun constructCamtResponse( * time range given as a function's parameter. */ if (dateRange != null) { + logger.debug("Querying c$type with date range: $dateRange") BankAccountStatementEntity.find { BankAccountStatementsTable.creationTime.between( dateRange.first, @@ -560,6 +565,7 @@ private fun constructCamtResponse( /** * No time range was given, hence pick the latest statement. */ + logger.debug("No date range was given for c$type, respond with latest document") BankAccountStatementEntity.find { BankAccountStatementsTable.bankAccount eq bankAccount.id }.lastOrNull().apply { @@ -569,7 +575,7 @@ private fun constructCamtResponse( } } if (ret.size == 0) throw EbicsRequestError( - "[EBICS_NO_DOWNLOAD_DATA_AVAILABLE]", + "[EBICS_NO_DOWNLOAD_DATA_AVAILABLE] as Camt $type", "090005" ) return ret diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -76,6 +76,7 @@ import tech.libeufin.util.ebics_h004.EbicsResponse import tech.libeufin.util.ebics_h004.EbicsTypes import validatePlainAmount import java.net.BindException +import java.time.ZoneOffset import java.util.* import kotlin.random.Random import kotlin.system.exitProcess @@ -148,7 +149,7 @@ class Camt053Tick : CliktCommand( val bankAccountLabel = it.transactionRef.account.label histories.putIfAbsent(bankAccountLabel, mutableListOf()) val historyIter = histories[bankAccountLabel] - historyIter?.add(getHistoryElementFromDbRow(it)) + historyIter?.add(getHistoryElementFromTransactionRow(it)) } /** * Resorting the closing (CLBD) balance of the last statement; will @@ -168,7 +169,7 @@ class Camt053Tick : CliktCommand( ) BankAccountStatementEntity.new { statementId = camtData.messageId - creationTime = Instant.now().toEpochMilli() + creationTime = getUTCnow().toInstant().epochSecond xmlMessage = camtData.camtMessage bankAccount = accountIter this.balanceClbd = balanceClbd.toPlainString() diff --git a/util/src/main/kotlin/time.kt b/util/src/main/kotlin/time.kt @@ -22,7 +22,7 @@ package tech.libeufin.util import java.time.* import java.time.format.DateTimeFormatter -private var LIBEUFIN_CLOCK = Clock.system(ZoneId.systemDefault()) +private var LIBEUFIN_CLOCK = Clock.system(ZoneOffset.UTC) fun setClock(rel: Duration) { LIBEUFIN_CLOCK = Clock.offset(LIBEUFIN_CLOCK, rel) @@ -30,29 +30,31 @@ fun setClock(rel: Duration) { fun getNow(): ZonedDateTime { return ZonedDateTime.now(LIBEUFIN_CLOCK) } +fun getUTCnow(): ZonedDateTime { + return ZonedDateTime.now(ZoneOffset.UTC) +} -fun LocalDateTime.toZonedString(): String { - return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(this.atZone(ZoneId.systemDefault())) +fun ZonedDateTime.toZonedString(): String { + return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(this) } -fun LocalDateTime.toDashedDate(): String { +fun ZonedDateTime.toDashedDate(): String { return DateTimeFormatter.ISO_DATE.format(this) } -fun parseDashedDate(date: String): LocalDateTime { +fun parseDashedDate(date: String): ZonedDateTime { val dtf = DateTimeFormatter.ISO_DATE - val asDate = LocalDate.parse(date, dtf) - return asDate.atStartOfDay() + return ZonedDateTime.parse(date, dtf) } -fun importDateFromMillis(millis: Long): LocalDateTime { - return LocalDateTime.ofInstant( +fun importDateFromMillis(millis: Long): ZonedDateTime { + return ZonedDateTime.ofInstant( Instant.ofEpochMilli(millis), - ZoneId.systemDefault() + ZoneOffset.UTC ) } fun LocalDateTime.millis(): Long { - val instant = Instant.from(this.atZone(ZoneId.systemDefault())) + val instant = Instant.from(this.atZone(ZoneOffset.UTC)) return instant.toEpochMilli() } \ No newline at end of file