libeufin

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

commit a5ad795d34402fe8e1f69c4c2edcaab670519853
parent f780713a659f4d2aa3d81adba1d02101454d3c34
Author: MS <ms@taler.net>
Date:   Mon, 23 Aug 2021 03:32:48 -1100

Fix balance calculation.

Do not search by IBAN, but by bank account name instead.

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 32+++++++++++++++++++-------------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt | 10++++++----
Mutil/src/main/kotlin/Config.kt | 9+++++----
Mutil/src/main/kotlin/Errors.kt | 5+++++
4 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -143,10 +143,11 @@ class MakeTransaction : CliktCommand("Wire-transfer money between Sandbox bank a private val creditAccount by option(help = "Label of the bank account receiving the payment").required() private val debitAccount by option(help = "Label of the bank account issuing the payment").required() private val amount by argument(help = "Amount, in the \$currency:x.y format") - private val subject by argument(help = "Payment's subject") + private val subjectArg by argument(name = "subject", help = "Payment's subject") override fun run() { - // TODO("Not yet implemented") + val dbConnString = getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME) + Database.connect(dbConnString) // check accounts exist transaction { val credit = BankAccountEntity.find { @@ -185,7 +186,7 @@ class MakeTransaction : CliktCommand("Wire-transfer money between Sandbox bank a it[debtorIban] = debit.iban it[debtorBic] = debit.bic it[debtorName] = debit.name - it[subject] = subject + it[subject] = subjectArg it[amount] = amountObj.amount.toString() it[currency] = amountObj.currency it[date] = Instant.now().toEpochMilli() @@ -200,7 +201,7 @@ class MakeTransaction : CliktCommand("Wire-transfer money between Sandbox bank a it[debtorIban] = debit.iban it[debtorBic] = debit.bic it[debtorName] = debit.name - it[subject] = subject + it[subject] = subjectArg it[amount] = amountObj.amount.toString() it[currency] = amountObj.currency it[date] = Instant.now().toEpochMilli() @@ -305,7 +306,7 @@ class SandboxCommand : CliktCommand(invokeWithoutSubcommand = true, printHelpOnE override fun run() = Unit } - + fun main(args: Array<String>) { SandboxCommand().subcommands(Serve(), ResetTables(), Config(), MakeTransaction()).main(args) } @@ -379,7 +380,7 @@ fun serverMain(dbName: String, port: Int) { val hostAuthPriv = transaction { val host = EbicsHostEntity.find { - EbicsHostsTable.hostID.upperCase() eq call.attributes.get(EbicsHostIdAttribute).toUpperCase() + EbicsHostsTable.hostID.upperCase() eq call.attributes.get(EbicsHostIdAttribute).uppercase() }.firstOrNull() ?: throw SandboxError( HttpStatusCode.InternalServerError, "Requested Ebics host ID not found." @@ -543,14 +544,19 @@ fun serverMain(dbName: String, port: Int) { get("/admin/bank-accounts/{label}") { val label = ensureNonNull(call.parameters["label"]) val ret = transaction { - val account = getAccountFromLabel(label) - val balance = balanceForAccount(account.iban) + val bankAccount = BankAccountEntity.find { + BankAccountsTable.label eq label + }.firstOrNull() ?: throw SandboxError( + HttpStatusCode.NotFound, + "Account '$label' not found" + ) + val balance = balanceForAccount(bankAccount) object { - val balance = "${account.currency}:${balance}" - val iban = account.iban - val bic = account.bic - val name = account.name - val label = account.label + val balance = "${bankAccount.currency}:${balance}" + val iban = bankAccount.iban + val bic = bankAccount.bic + val name = bankAccount.name + val label = bankAccount.label } } call.respond(ret) diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt @@ -1,6 +1,7 @@ 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 @@ -27,18 +28,19 @@ fun getAccountFromLabel(accountLabel: String): BankAccountEntity { } } -fun balanceForAccount(iban: String): BigDecimal { - logger.debug("Calculating balance for account: ${iban}") +fun balanceForAccount(bankAccount: BankAccountEntity): BigDecimal { var balance = BigDecimal.ZERO transaction { BankAccountTransactionsTable.select { - BankAccountTransactionsTable.creditorIban eq iban + BankAccountTransactionsTable.direction eq "CRDT" and ( + BankAccountTransactionsTable.account eq bankAccount.id) }.forEach { val amount = parseDecimal(it[amount]) balance += amount } BankAccountTransactionsTable.select { - BankAccountTransactionsTable.debtorIban eq iban + BankAccountTransactionsTable.direction eq "DBIT" and ( + BankAccountTransactionsTable.account eq bankAccount.id) }.forEach { val amount = parseDecimal(it[amount]) balance -= amount diff --git a/util/src/main/kotlin/Config.kt b/util/src/main/kotlin/Config.kt @@ -5,6 +5,7 @@ import ch.qos.logback.classic.LoggerContext import ch.qos.logback.classic.util.ContextInitializer import ch.qos.logback.core.util.Loader import org.slf4j.LoggerFactory +import printLnErr import kotlin.system.exitProcess fun getVersion(): String { @@ -52,10 +53,10 @@ fun setLogLevel(logLevel: String?) { fun getDbConnFromEnv(varName: String): String { val dbConnStr = System.getenv(varName) if (dbConnStr.isNullOrBlank() or dbConnStr.isNullOrEmpty()) { - println("DB connection string not found/valid in the env variable $varName.") - println("The following two examples are valid connection strings:") - println("jdbc:sqlite:/tmp/libeufindb.sqlite3") - println("jdbc:postgresql://localhost:5432/libeufindb?user=Foo&password=secret") + printLnErr("DB connection string not found/valid in the env variable $varName.") + printLnErr("The following two examples are valid connection strings:") + printLnErr("jdbc:sqlite:/tmp/libeufindb.sqlite3") + printLnErr("jdbc:postgresql://localhost:5432/libeufindb?user=Foo&password=secret") exitProcess(1) } return dbConnStr diff --git a/util/src/main/kotlin/Errors.kt b/util/src/main/kotlin/Errors.kt @@ -44,4 +44,9 @@ fun execThrowableOrTerminate(func: () -> Unit) { println(e.message) exitProcess(1) } +} + +fun printLnErr(errorMessage: String) { + System.err.println(errorMessage) + } \ No newline at end of file