libeufin

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

commit 67bef53ab7916c39ec524f42d35f2b485f69b649
parent 534cff2a3b34e848fa2067cb461a7d157915cae4
Author: MS <ms@taler.net>
Date:   Sun, 29 Aug 2021 23:36:07 -1100

Sandbox database changes, to implement statement report.

The transactions table becomes a LongIntId, and a new table
now holds the fresh (= not yet included in a statement) transactions
until new statements get generated.  After that, the table of
fresh transactions get emptied.

Making the transaction table a LongIntId helps to keep
references to it from within the table of fresh transactions.

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt | 54+++++++++++++++++++++++++++++++++++++++++++++---------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 66+++++++++++++++++++++++++++++++++---------------------------------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 257++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt | 46++++++++++++++++++++++------------------------
Msandbox/src/test/kotlin/BalanceTest.kt | 106+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msandbox/src/test/kotlin/DBTest.kt | 52+++++++++++++++++++++++++++++-----------------------
Msandbox/src/test/kotlin/StringsTest.kt | 10----------
7 files changed, 312 insertions(+), 279 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt @@ -282,10 +282,25 @@ class EbicsUploadTransactionChunkEntity(id: EntityID<String>) : Entity<String>(i var chunkContent by EbicsUploadTransactionChunksTable.chunkContent } + +/** + * Holds those transactions that aren't yet reported in a Camt.053 document. + * After reporting those, the table gets emptied. Rows are merely references + * to the main ledger. + */ +object BankAccountFreshTransactionsTable : LongIdTable() { + val transactionRef = reference("transaction", BankAccountTransactionsTable) +} +class BankAccountFreshTransactionEntity(id: EntityID<Long>) : LongEntity(id) { + companion object : LongEntityClass<BankAccountFreshTransactionEntity>(BankAccountFreshTransactionsTable) + + var transactionRef by BankAccountTransactionEntity referencedOn BankAccountFreshTransactionsTable.transactionRef +} + /** * Table that keeps all the payments initiated by PAIN.001. */ -object BankAccountTransactionsTable : Table() { +object BankAccountTransactionsTable : LongIdTable() { val creditorIban = text("creditorIban") val creditorBic = text("creditorBic").nullable() val creditorName = text("creditorName") @@ -293,7 +308,7 @@ object BankAccountTransactionsTable : Table() { val debtorBic = text("debtorBic").nullable() val debtorName = text("debtorName") val subject = text("subject") - val amount = text("amount") + val amount = text("amount") // NOT the usual $currency:x.y, but a BigInt as string val currency = text("currency") val date = long("date") @@ -304,18 +319,38 @@ object BankAccountTransactionsTable : Table() { /** * Payment information ID, which is a reference to the payment initiation - * that triggered this transaction. Typically only available with outgoing transactions. + * that triggered this transaction. Typically, only available with outgoing transactions. */ val pmtInfId = text("pmtInfId").nullable() val direction = text("direction") val account = reference("account", BankAccountsTable) - - // indicates whether the transaction got included in a C53 statement. - val c53 = bool("c53").default(false) +} + +class BankAccountTransactionEntity(id: EntityID<Long>) : LongEntity(id) { + companion object : LongEntityClass<BankAccountTransactionEntity>(BankAccountTransactionsTable) { + override fun new(init: BankAccountTransactionEntity.() -> Unit): BankAccountTransactionEntity { + val freshTx = super.new(init) + BankAccountFreshTransactionsTable.insert { + it[transactionRef] = freshTx.id + } + return freshTx + } + } - // It can't be unique (anymore), because one table might contain - // the same payment twice: once as DBIT and once as CRDT. - // override val primaryKey = PrimaryKey(pmtInfId) + var creditorIban by BankAccountTransactionsTable.creditorIban + var creditorBic by BankAccountTransactionsTable.creditorBic + var creditorName by BankAccountTransactionsTable.creditorName + var debtorIban by BankAccountTransactionsTable.debtorIban + var debtorBic by BankAccountTransactionsTable.debtorBic + var debtorName by BankAccountTransactionsTable.debtorName + var subject by BankAccountTransactionsTable.subject + var amount by BankAccountTransactionsTable.amount + var currency by BankAccountTransactionsTable.currency + var date by BankAccountTransactionsTable.date + var accountServicerReference by BankAccountTransactionsTable.accountServicerReference + var pmtInfId by BankAccountTransactionsTable.pmtInfId + var direction by BankAccountTransactionsTable.direction + var account by BankAccountEntity referencedOn BankAccountTransactionsTable.account } /** @@ -388,6 +423,7 @@ fun dbCreateTables(dbConnectionString: String) { EbicsUploadTransactionChunksTable, EbicsOrderSignaturesTable, BankAccountTransactionsTable, + BankAccountFreshTransactionsTable, BankAccountsTable, BankAccountReportsTable, BankAccountStatementsTable diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -561,41 +561,41 @@ private fun handleCct(paymentRequest: String) { val parseResult = parsePain001(paymentRequest) transaction { try { - BankAccountTransactionsTable.insert { - it[account] = getBankAccountFromIban(parseResult.debtorIban).id - it[creditorIban] = parseResult.creditorIban - it[creditorName] = parseResult.creditorName - it[creditorBic] = parseResult.creditorBic - it[debtorIban] = parseResult.debtorIban - it[debtorName] = parseResult.debtorName - it[debtorBic] = parseResult.debtorBic - it[subject] = parseResult.subject - it[amount] = parseResult.amount.toString() - it[currency] = parseResult.currency - it[date] = Instant.now().toEpochMilli() - it[pmtInfId] = parseResult.pmtInfId - it[accountServicerReference] = "sandboxref-${getRandomString(16)}" - it[direction] = "DBIT" + BankAccountTransactionEntity.new { + account = getBankAccountFromIban(parseResult.debtorIban) + creditorIban = parseResult.creditorIban + creditorName = parseResult.creditorName + creditorBic = parseResult.creditorBic + debtorIban = parseResult.debtorIban + debtorName = parseResult.debtorName + debtorBic = parseResult.debtorBic + subject = parseResult.subject + amount = parseResult.amount.toString() + currency = parseResult.currency + date = Instant.now().toEpochMilli() + pmtInfId = parseResult.pmtInfId + accountServicerReference = "sandboxref-${getRandomString(16)}" + direction = "DBIT" } val maybeLocalCreditor = BankAccountEntity.find( BankAccountsTable.iban eq parseResult.creditorIban ).firstOrNull() if (maybeLocalCreditor != null) { - BankAccountTransactionsTable.insert { - it[account] = maybeLocalCreditor.id - it[creditorIban] = parseResult.creditorIban - it[creditorName] = parseResult.creditorName - it[creditorBic] = parseResult.creditorBic - it[debtorIban] = parseResult.debtorIban - it[debtorName] = parseResult.debtorName - it[debtorBic] = parseResult.debtorBic - it[subject] = parseResult.subject - it[amount] = parseResult.amount.toString() - it[currency] = parseResult.currency - it[date] = Instant.now().toEpochMilli() - it[pmtInfId] = parseResult.pmtInfId - it[accountServicerReference] = "sandboxref-${getRandomString(16)}" - it[direction] = "CRDT" + BankAccountTransactionEntity.new { + account = maybeLocalCreditor + creditorIban = parseResult.creditorIban + creditorName = parseResult.creditorName + creditorBic = parseResult.creditorBic + debtorIban = parseResult.debtorIban + debtorName = parseResult.debtorName + debtorBic = parseResult.debtorBic + subject = parseResult.subject + amount = parseResult.amount.toString() + currency = parseResult.currency + date = Instant.now().toEpochMilli() + pmtInfId = parseResult.pmtInfId + accountServicerReference = "sandboxref-${getRandomString(16)}" + direction = "CRDT" } } } catch (e: ExposedSQLException) { @@ -776,7 +776,7 @@ private suspend fun ApplicationCall.handleEbicsHpb( private fun ApplicationCall.ensureEbicsHost(requestHostID: String): EbicsHostPublicInfo { return transaction { val ebicsHost = - EbicsHostEntity.find { EbicsHostsTable.hostID.upperCase() eq requestHostID.toUpperCase() }.firstOrNull() + EbicsHostEntity.find { EbicsHostsTable.hostID.upperCase() eq requestHostID.uppercase(Locale.getDefault()) }.firstOrNull() if (ebicsHost == null) { logger.warn("client requested unknown HostID ${requestHostID}") throw EbicsKeyManagementError("[EBICS_INVALID_HOST_ID]", "091011") @@ -1105,14 +1105,14 @@ private fun makeRequestContext(requestObject: EbicsRequest): RequestContext { val staticHeader = requestObject.header.static val requestedHostId = staticHeader.hostID val ebicsHost = - EbicsHostEntity.find { EbicsHostsTable.hostID.upperCase() eq requestedHostId.toUpperCase() } + EbicsHostEntity.find { EbicsHostsTable.hostID.upperCase() eq requestedHostId.uppercase(Locale.getDefault()) } .firstOrNull() val requestTransactionID = requestObject.header.static.transactionID var downloadTransaction: EbicsDownloadTransactionEntity? = null var uploadTransaction: EbicsUploadTransactionEntity? = null val subscriber = if (requestTransactionID != null) { println("finding subscriber by transactionID $requestTransactionID") - downloadTransaction = EbicsDownloadTransactionEntity.findById(requestTransactionID.toUpperCase()) + downloadTransaction = EbicsDownloadTransactionEntity.findById(requestTransactionID.uppercase(Locale.getDefault())) if (downloadTransaction != null) { downloadTransaction.subscriber } else { diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -71,18 +71,6 @@ import io.ktor.http.* import io.ktor.http.content.* import io.ktor.request.* import io.ktor.util.date.* -import tech.libeufin.sandbox.BankAccountTransactionsTable.accountServicerReference -import tech.libeufin.sandbox.BankAccountTransactionsTable.amount -import tech.libeufin.sandbox.BankAccountTransactionsTable.creditorBic -import tech.libeufin.sandbox.BankAccountTransactionsTable.creditorIban -import tech.libeufin.sandbox.BankAccountTransactionsTable.creditorName -import tech.libeufin.sandbox.BankAccountTransactionsTable.currency -import tech.libeufin.sandbox.BankAccountTransactionsTable.date -import tech.libeufin.sandbox.BankAccountTransactionsTable.debtorBic -import tech.libeufin.sandbox.BankAccountTransactionsTable.debtorIban -import tech.libeufin.sandbox.BankAccountTransactionsTable.debtorName -import tech.libeufin.sandbox.BankAccountTransactionsTable.direction -import tech.libeufin.sandbox.BankAccountTransactionsTable.pmtInfId import tech.libeufin.util.* import tech.libeufin.util.ebics_h004.EbicsResponse import tech.libeufin.util.ebics_h004.EbicsTypes @@ -139,7 +127,24 @@ class Camt053Tick : CliktCommand( "will be inserted in a new Camt.053 report" ) { override fun run() { - TODO("Not yet implemented") + val dbConnString = getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME) + Database.connect(dbConnString) + dbCreateTables(dbConnString) + transaction { + BankAccountEntity.all().forEach { accountIter-> + val accountRet = mutableListOf<String>() + BankAccountFreshTransactionEntity.all().forEach { freshTx -> + accountRet.add( + "${freshTx.transactionRef.subject}: " + + "${freshTx.transactionRef.amount} ${freshTx.transactionRef.currency} " + + "${freshTx.transactionRef.direction}" + ) + } + println("Bank account ${accountIter.label} found fresh transactions:") + accountRet.forEach { println(it) } + } + BankAccountFreshTransactionsTable.deleteAll() + } } } class MakeTransaction : CliktCommand("Wire-transfer money between Sandbox bank accounts") { @@ -187,35 +192,35 @@ class MakeTransaction : CliktCommand("Wire-transfer money between Sandbox bank a exitProcess(1) } val randId = getRandomString(16) - BankAccountTransactionsTable.insert { - it[creditorIban] = credit.iban - it[creditorBic] = credit.bic - it[creditorName] = credit.name - it[debtorIban] = debit.iban - it[debtorBic] = debit.bic - it[debtorName] = debit.name - it[subject] = subjectArg - it[amount] = amountObj.amount.toString() - it[currency] = amountObj.currency - it[date] = Instant.now().toEpochMilli() - it[accountServicerReference] = "sandbox-$randId" - it[account] = debit.id - it[direction] = "DBIT" - } - BankAccountTransactionsTable.insert { - it[creditorIban] = credit.iban - it[creditorBic] = credit.bic - it[creditorName] = credit.name - it[debtorIban] = debit.iban - it[debtorBic] = debit.bic - it[debtorName] = debit.name - it[subject] = subjectArg - it[amount] = amountObj.amount.toString() - it[currency] = amountObj.currency - it[date] = Instant.now().toEpochMilli() - it[accountServicerReference] = "sandbox-$randId" - it[account] = credit.id - it[direction] = "CRDT" + BankAccountTransactionEntity.new { + creditorIban = credit.iban + creditorBic = credit.bic + creditorName = credit.name + debtorIban = debit.iban + debtorBic = debit.bic + debtorName = debit.name + subject = subjectArg + amount = amountObj.amount.toString() + currency = amountObj.currency + date = Instant.now().toEpochMilli() + accountServicerReference = "sandbox-$randId" + account = debit + direction = "DBIT" + } + BankAccountTransactionEntity.new { + creditorIban = credit.iban + creditorBic = credit.bic + creditorName = credit.name + debtorIban = debit.iban + debtorBic = debit.bic + debtorName = debit.name + subject = subjectArg + amount = amountObj.amount.toString() + currency = amountObj.currency + date = Instant.now().toEpochMilli() + accountServicerReference = "sandbox-$randId" + account = credit + direction = "CRDT" } } } @@ -597,20 +602,20 @@ fun serverMain(dbName: String, port: Int) { transaction { val account = getBankAccountFromLabel(accountLabel) val randId = getRandomString(16) - BankAccountTransactionsTable.insert { - it[creditorIban] = account.iban - it[creditorBic] = account.bic - it[creditorName] = account.name - it[debtorIban] = body.debtorIban - it[debtorBic] = reqDebtorBic - it[debtorName] = body.debtorName - it[subject] = body.subject - it[amount] = body.amount - it[currency] = account.currency - it[date] = Instant.now().toEpochMilli() - it[accountServicerReference] = "sandbox-$randId" - it[BankAccountTransactionsTable.account] = account.id - it[direction] = "CRDT" + BankAccountTransactionEntity.new { + creditorIban = account.iban + creditorBic = account.bic + creditorName = account.name + debtorIban = body.debtorIban + debtorBic = reqDebtorBic + debtorName = body.debtorName + subject = body.subject + amount = body.amount + currency = account.currency + date = Instant.now().toEpochMilli() + accountServicerReference = "sandbox-$randId" + this.account = account + direction = "CRDT" } } call.respond(object {}) @@ -627,20 +632,20 @@ fun serverMain(dbName: String, port: Int) { val randId = getRandomString(16) transaction { val localIban = if (body.direction == "DBIT") body.debtorIban else body.creditorIban - BankAccountTransactionsTable.insert { - it[creditorIban] = body.creditorIban - it[creditorBic] = body.creditorBic - it[creditorName] = body.creditorName - it[debtorIban] = body.debtorIban - it[debtorBic] = body.debtorBic - it[debtorName] = body.debtorName - it[subject] = body.subject - it[amount] = body.amount - it[currency] = body.currency - it[date] = Instant.now().toEpochMilli() - it[accountServicerReference] = "sandbox-$randId" - it[account] = getBankAccountFromIban(localIban).id - it[direction] = body.direction + BankAccountTransactionEntity.new { + creditorIban = body.creditorIban + creditorBic = body.creditorBic + creditorName = body.creditorName + debtorIban = body.debtorIban + debtorBic = body.debtorBic + debtorName = body.debtorName + subject = body.subject + amount = body.amount + currency = body.currency + date = Instant.now().toEpochMilli() + accountServicerReference = "sandbox-$randId" + account = getBankAccountFromIban(localIban) + direction = body.direction } } call.respondText("Payment created") @@ -702,33 +707,34 @@ fun serverMain(dbName: String, port: Int) { val accountLabel = ensureNonNull(call.parameters["label"]) transaction { val account = getBankAccountFromLabel(accountLabel) - BankAccountTransactionsTable.select { BankAccountTransactionsTable.account eq account.id } - .forEach { - ret.payments.add( - PaymentInfo( - accountLabel = account.label, - creditorIban = it[creditorIban], - // FIXME: We need to modify the transactions table to have an actual - // account servicer reference here. - accountServicerReference = it[accountServicerReference], - paymentInformationId = it[pmtInfId], - debtorIban = it[debtorIban], - subject = it[BankAccountTransactionsTable.subject], - date = GMTDate(it[date]).toHttpDate(), - amount = it[amount], - creditorBic = it[creditorBic], - creditorName = it[creditorName], - debtorBic = it[debtorBic], - debtorName = it[debtorName], - currency = it[currency], - creditDebitIndicator = when (it[direction]) { - "CRDT" -> "credit" - "DBIT" -> "debit" - else -> throw Error("invalid direction") - } - ) + BankAccountTransactionEntity.find { + BankAccountTransactionsTable.account eq account.id + }.forEach { + ret.payments.add( + PaymentInfo( + accountLabel = account.label, + creditorIban = it.creditorIban, + // FIXME: We need to modify the transactions table to have an actual + // account servicer reference here. + accountServicerReference = it.accountServicerReference, + paymentInformationId = it.pmtInfId, + debtorIban = it.debtorIban, + subject = it.subject, + date = GMTDate(it.date).toHttpDate(), + amount = it.amount, + creditorBic = it.creditorBic, + creditorName = it.creditorName, + debtorBic = it.debtorBic, + debtorName = it.debtorName, + currency = it.currency, + creditDebitIndicator = when (it.direction) { + "CRDT" -> "credit" + "DBIT" -> "debit" + else -> throw Error("invalid direction") + } ) - } + ) + } } } call.respond(ret) @@ -742,40 +748,40 @@ fun serverMain(dbName: String, port: Int) { run { val amount = Random.nextLong(5, 25) - BankAccountTransactionsTable.insert { - it[creditorIban] = account.iban - it[creditorBic] = account.bic - it[creditorName] = account.name - it[debtorIban] = "DE64500105178797276788" - it[debtorBic] = "DEUTDEBB101" - it[debtorName] = "Max Mustermann" - it[subject] = "sample transaction $transactionReferenceCrdt" - it[BankAccountTransactionsTable.amount] = amount.toString() - it[currency] = account.currency - it[date] = Instant.now().toEpochMilli() - it[accountServicerReference] = transactionReferenceCrdt - it[BankAccountTransactionsTable.account] = account.id - it[direction] = "CRDT" + BankAccountTransactionEntity.new { + creditorIban = account.iban + creditorBic = account.bic + creditorName = account.name + debtorIban = "DE64500105178797276788" + debtorBic = "DEUTDEBB101" + debtorName = "Max Mustermann" + subject = "sample transaction $transactionReferenceCrdt" + this.amount = amount.toString() + currency = account.currency + date = Instant.now().toEpochMilli() + accountServicerReference = transactionReferenceCrdt + this.account = account + direction = "CRDT" } } run { val amount = Random.nextLong(5, 25) - BankAccountTransactionsTable.insert { - it[debtorIban] = account.iban - it[debtorBic] = account.bic - it[debtorName] = account.name - it[creditorIban] = "DE64500105178797276788" - it[creditorBic] = "DEUTDEBB101" - it[creditorName] = "Max Mustermann" - it[subject] = "sample transaction $transactionReferenceDbit" - it[BankAccountTransactionsTable.amount] = amount.toString() - it[currency] = account.currency - it[date] = Instant.now().toEpochMilli() - it[accountServicerReference] = transactionReferenceDbit - it[BankAccountTransactionsTable.account] = account.id - it[direction] = "DBIT" + BankAccountTransactionEntity.new { + debtorIban = account.iban + debtorBic = account.bic + debtorName = account.name + creditorIban = "DE64500105178797276788" + creditorBic = "DEUTDEBB101" + creditorName = "Max Mustermann" + subject = "sample transaction $transactionReferenceDbit" + this.amount = amount.toString() + currency = account.currency + date = Instant.now().toEpochMilli() + accountServicerReference = transactionReferenceDbit + this.account = account + direction = "DBIT" } } } @@ -895,4 +901,4 @@ fun serverMain(dbName: String, port: Int) { logger.error(e.message) exitProcess(1) } -} -\ No newline at end of file +} diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt @@ -2,12 +2,9 @@ package tech.libeufin.sandbox import io.ktor.http.* import org.jetbrains.exposed.sql.and -import org.jetbrains.exposed.sql.or -import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction import org.slf4j.Logger import org.slf4j.LoggerFactory -import tech.libeufin.sandbox.BankAccountTransactionsTable.amount import tech.libeufin.util.RawPayment import tech.libeufin.util.importDateFromMillis import tech.libeufin.util.parseDecimal @@ -52,18 +49,18 @@ fun balanceForAccount(history: List<RawPayment>): BigDecimal { fun balanceForAccount(bankAccount: BankAccountEntity): BigDecimal { var balance = BigDecimal.ZERO transaction { - BankAccountTransactionsTable.select { + BankAccountTransactionEntity.find { BankAccountTransactionsTable.direction eq "CRDT" and ( BankAccountTransactionsTable.account eq bankAccount.id) }.forEach { - val amount = parseDecimal(it[amount]) + val amount = parseDecimal(it.amount) balance += amount } - BankAccountTransactionsTable.select { + BankAccountTransactionEntity.find { BankAccountTransactionsTable.direction eq "DBIT" and ( BankAccountTransactionsTable.account eq bankAccount.id) }.forEach { - val amount = parseDecimal(it[amount]) + val amount = parseDecimal(it.amount) balance -= amount } } @@ -87,29 +84,31 @@ fun historyForAccount(bankAccount: BankAccountEntity): List<RawPayment> { FIXME: add the following condition too: and (BankAccountTransactionsTable.date.between(start.millis, end.millis)) */ - BankAccountTransactionsTable.select { BankAccountTransactionsTable.account eq bankAccount.id }.forEach { + BankAccountTransactionEntity.find { + BankAccountTransactionsTable.account eq bankAccount.id + }.forEach { history.add( RawPayment( - subject = it[BankAccountTransactionsTable.subject], - creditorIban = it[BankAccountTransactionsTable.creditorIban], - creditorBic = it[BankAccountTransactionsTable.creditorBic], - creditorName = it[BankAccountTransactionsTable.creditorName], - debtorIban = it[BankAccountTransactionsTable.debtorIban], - debtorBic = it[BankAccountTransactionsTable.debtorBic], - debtorName = it[BankAccountTransactionsTable.debtorName], - date = importDateFromMillis(it[BankAccountTransactionsTable.date]).toDashedDate(), - amount = it[BankAccountTransactionsTable.amount], - currency = it[BankAccountTransactionsTable.currency], + subject = it.subject, + creditorIban = it.creditorIban, + creditorBic = it.creditorBic, + creditorName = it.creditorName, + debtorIban = it.debtorIban, + debtorBic = it.debtorBic, + debtorName = it.debtorName, + date = importDateFromMillis(it.date).toDashedDate(), + amount = it.amount, + currency = it.currency, // The line below produces a value too long (>35 chars), // and it makes the document invalid! - // uid = "${it[pmtInfId]}-${it[msgId]}" - uid = it[BankAccountTransactionsTable.accountServicerReference], - direction = it[BankAccountTransactionsTable.direction], - pmtInfId = it[BankAccountTransactionsTable.pmtInfId] + // uid = "${it.pmtInfId}-${it.msgId}" + uid = it.accountServicerReference, + direction = it.direction, + pmtInfId = it.pmtInfId ) ) } } return history -} -\ No newline at end of file +} diff --git a/sandbox/src/test/kotlin/BalanceTest.kt b/sandbox/src/test/kotlin/BalanceTest.kt @@ -1,14 +1,9 @@ -import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.insert import org.jetbrains.exposed.sql.transactions.transaction import org.junit.Test -import tech.libeufin.sandbox.BankAccountEntity -import tech.libeufin.sandbox.BankAccountTransactionsTable -import tech.libeufin.sandbox.BankAccountsTable -import tech.libeufin.sandbox.balanceForAccount +import tech.libeufin.sandbox.* import tech.libeufin.util.millis -import java.math.BigInteger import java.time.LocalDateTime class BalanceTest { @@ -17,7 +12,11 @@ class BalanceTest { fun balanceTest() { withTestDatabase { transaction { - SchemaUtils.create(BankAccountTransactionsTable) + SchemaUtils.create( + BankAccountsTable, + BankAccountTransactionsTable, + BankAccountFreshTransactionsTable + ) val one = BankAccountEntity.new { name = "Person 1" iban = "IBAN 1" @@ -25,56 +24,56 @@ class BalanceTest { label = "label 1" currency = "EUR" } - BankAccountTransactionsTable.insert { - it[account] = one.id - it[creditorIban] = "earns" - it[creditorBic] = "BIC" - it[creditorName] = "Creditor Name" - it[debtorIban] = "spends" - it[debtorBic] = "BIC" - it[debtorName] = "Debitor Name" - it[subject] = "deal" - it[amount] = "1" - it[date] = LocalDateTime.now().millis() - it[currency] = "EUR" - it[pmtInfId] = "0" - it[direction] = "CRDT" - it[accountServicerReference] = "test-account-servicer-reference" + BankAccountTransactionEntity.new { + account = one + creditorIban = "earns" + creditorBic = "BIC" + creditorName = "Creditor Name" + debtorIban = "spends" + debtorBic = "BIC" + debtorName = "Debitor Name" + subject = "deal" + amount = "1" + date = LocalDateTime.now().millis() + currency = "EUR" + pmtInfId = "0" + direction = "CRDT" + accountServicerReference = "test-account-servicer-reference" } - BankAccountTransactionsTable.insert { - it[account] = one.id - it[creditorIban] = "earns" - it[creditorBic] = "BIC" - it[creditorName] = "Creditor Name" - it[debtorIban] = "spends" - it[debtorBic] = "BIC" - it[debtorName] = "Debitor Name" - it[subject] = "deal" - it[amount] = "1" - it[date] = LocalDateTime.now().millis() - it[currency] = "EUR" - it[pmtInfId] = "0" - it[direction] = "CRDT" - it[accountServicerReference] = "test-account-servicer-reference" + BankAccountTransactionEntity.new { + account = one + creditorIban = "earns" + creditorBic = "BIC" + creditorName = "Creditor Name" + debtorIban = "spends" + debtorBic = "BIC" + debtorName = "Debitor Name" + subject = "deal" + amount = "1" + date = LocalDateTime.now().millis() + currency = "EUR" + pmtInfId = "0" + direction = "CRDT" + accountServicerReference = "test-account-servicer-reference" } - BankAccountTransactionsTable.insert { - it[account] = one.id - it[creditorIban] = "earns" - it[creditorBic] = "BIC" - it[creditorName] = "Creditor Name" - it[debtorIban] = "spends" - it[debtorBic] = "BIC" - it[debtorName] = "Debitor Name" - it[subject] = "deal" - it[amount] = "1" - it[date] = LocalDateTime.now().millis() - it[currency] = "EUR" - it[pmtInfId] = "0" - it[direction] = "DBIT" - it[accountServicerReference] = "test-account-servicer-reference" + BankAccountTransactionEntity.new { + account = one + creditorIban = "earns" + creditorBic = "BIC" + creditorName = "Creditor Name" + debtorIban = "spends" + debtorBic = "BIC" + debtorName = "Debitor Name" + subject = "deal" + amount = "1" + date = LocalDateTime.now().millis() + currency = "EUR" + pmtInfId = "0" + direction = "DBIT" + accountServicerReference = "test-account-servicer-reference" } assert(java.math.BigDecimal.ONE == balanceForAccount(one)) } } } -} -\ No newline at end of file +} diff --git a/sandbox/src/test/kotlin/DBTest.kt b/sandbox/src/test/kotlin/DBTest.kt @@ -21,9 +21,7 @@ import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction import org.junit.Test -import tech.libeufin.sandbox.BankAccountTransactionsTable -import tech.libeufin.sandbox.BankAccountsTable -import tech.libeufin.sandbox.dbDropTables +import tech.libeufin.sandbox.* import tech.libeufin.util.millis import tech.libeufin.util.parseDashedDate import java.io.File @@ -64,31 +62,39 @@ class DBTest { fun betweenDates() { withTestDatabase { transaction { - SchemaUtils.create(BankAccountTransactionsTable) - BankAccountTransactionsTable.insert { - it[account] = EntityID(0, BankAccountsTable) - it[creditorIban] = "earns" - it[creditorBic] = "BIC" - it[creditorName] = "Creditor Name" - it[debtorIban] = "spends" - it[debtorBic] = "BIC" - it[debtorName] = "Debitor Name" - it[subject] = "deal" - it[amount] = "EUR:1" - it[date] = LocalDateTime.now().millis() - it[currency] = "EUR" - it[pmtInfId] = "0" - it[direction] = "DBIT" - it[accountServicerReference] = "test-account-servicer-reference" + SchemaUtils.create( + BankAccountTransactionsTable, + BankAccountFreshTransactionsTable + ) + val bankAccount = BankAccountEntity.new { + iban = "iban" + bic = "bic" + name = "name" + label = "label" + currency = "TESTKUDOS" + } + BankAccountTransactionEntity.new { + account = bankAccount + creditorIban = "earns" + creditorBic = "BIC" + creditorName = "Creditor Name" + debtorIban = "spends" + debtorBic = "BIC" + debtorName = "Debitor Name" + subject = "deal" + amount = "EUR:1" + date = LocalDateTime.now().millis() + currency = "EUR" + pmtInfId = "0" + direction = "DBIT" + accountServicerReference = "test-account-servicer-reference" } } val result = transaction { addLogger(StdOutSqlLogger) - BankAccountTransactionsTable.select { + BankAccountTransactionEntity.find { BankAccountTransactionsTable.date.between( - parseDashedDate( - "1970-01-01" - ).millis(), + parseDashedDate("1970-01-01").millis(), LocalDateTime.now().millis() ) }.firstOrNull() diff --git a/sandbox/src/test/kotlin/StringsTest.kt b/sandbox/src/test/kotlin/StringsTest.kt @@ -1,15 +1,5 @@ -import org.jetbrains.exposed.dao.id.EntityID -import org.jetbrains.exposed.sql.SchemaUtils -import org.jetbrains.exposed.sql.insert -import org.jetbrains.exposed.sql.transactions.transaction import org.junit.Test -import tech.libeufin.sandbox.BankAccountTransactionsTable -import tech.libeufin.sandbox.BankAccountsTable -import tech.libeufin.sandbox.balanceForAccount -import tech.libeufin.util.millis import tech.libeufin.util.validateBic -import java.math.BigInteger -import java.time.LocalDateTime class StringsTest {