libeufin

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

commit b3dd9241a74df41949875ccf020da7b98682ba9c
parent 6ebe691de905c96b5bb30649b12822b5d606191a
Author: Antoine A <>
Date:   Fri, 22 Nov 2024 17:52:24 +0100

nexus: improve import & export cmd
update batches status on export
accept many file at once on import

Diffstat:
Mnexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt | 37++++++++++++++++++++++++++++++-------
Mnexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt | 29++++++++++++++++++++---------
2 files changed, 50 insertions(+), 16 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt @@ -29,6 +29,7 @@ import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.* +import com.github.ajalt.mordant.terminal.* import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.ebics.* @@ -286,11 +287,14 @@ class ExportCmt: CliktCommand("export") { override fun run() = cliCmd(logger, common.log) { nexusConfig(common.config).withDb { db, cfg -> + // Create and get pending batches + db.initiated.batch(Instant.now(), randEbicsId()) + val batches = db.initiated.submittable(cfg.currency) + var nbTx: Int = 0 ZipOutputStream(BufferedOutputStream(FileOutputStream(out))).use { zip -> - db.initiated.batch(Instant.now(), randEbicsId()) val ebicsCfg = cfg.ebics - db.initiated.submittable(cfg.currency).forEach { batch -> + for (batch in batches) { nbTx = batch.payments.size val entry = ZipEntry("${batch.creationDate.toDateTimeFilePath()}-${batch.messageId}.xml") zip.putNextEntry(entry) @@ -303,6 +307,23 @@ class ExportCmt: CliktCommand("export") { } } println("Exported $nbTx transactions in $out") + + // Update batches status + val now = Instant.now() + val t = Terminal() + for (batch in batches) { + val filename = "${batch.creationDate.toDateTimeFilePath()}-${batch.messageId}.xml" + val success = YesNoPrompt("Was $filename upload sucessfull?", t).ask() + if (success == true) { + db.initiated.batchSubmissionSuccess(batch.id, now, null) + } else if (success == false) { + val permanent = YesNoPrompt("Is the error permanent?", t).ask() + val msg = StringPrompt("Error msg", t).ask() + if (permanent != null) { + db.initiated.batchSubmissionFailure(batch.id, now, msg, permanent) + } + } + } } } } @@ -311,15 +332,17 @@ class ImportCmt: CliktCommand("import") { override fun help(context: Context) = "Import EBICS camt files" private val common by CommonOption() - private val source by argument().file() + private val sources by argument().file().multiple(required = true) override fun run() = cliCmd(logger, common.log) { nexusConfig(common.config).withDb { db, cfg -> - var nbTx: Int = 0 - source.inputStream().use { xml -> - nbTx += registerTxs(db, cfg, xml) + for (source in sources) { + var nbTx: Int = 0 + source.inputStream().use { xml -> + nbTx += registerTxs(db, cfg, xml) + } + println("Imported $nbTx transactions from $source") } - println("Imported $nbTx transactions from $source") } } } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt @@ -67,7 +67,7 @@ class InitiatedDAO(private val db: Database) { suspend fun batchSubmissionSuccess( id: Long, timestamp: Instant, - orderId: String + orderId: String? ) = db.serializableTransaction { tx -> // Update batch status val updated = tx.withStatement( @@ -105,34 +105,45 @@ class InitiatedDAO(private val db: Database) { suspend fun batchSubmissionFailure( id: Long, timestamp: Instant, - msg: String? + msg: String?, + permanent: Boolean = false ) = db.serializableTransaction { tx -> // Update batch status tx.withStatement( """ UPDATE initiated_outgoing_batches - SET status = 'transient_failure' + SET status = ?::submission_state ,submission_date = ? ,status_msg = ? ,submission_counter = submission_counter + 1 WHERE initiated_outgoing_batch_id = ? """ ) { - setLong(1, timestamp.micros()) - setString(2, msg) - setLong(3, id) + if (permanent) { + setString(1, StatusUpdate.permanent_failure.name) + } else { + setString(1, StatusUpdate.transient_failure.name) + } + setLong(2, timestamp.micros()) + setString(3, msg) + setLong(4, id) execute() } // Update unsettled batch's transaction status tx.withStatement( """ UPDATE initiated_outgoing_transactions - SET status = 'transient_failure', status_msg = ? + SET status = ?::submission_state, status_msg = ? WHERE initiated_outgoing_batch_id = ? AND $UNSETTLED_FILTER """ ) { - setString(1, msg) - setLong(2, id) + if (permanent) { + setString(1, StatusUpdate.permanent_failure.name) + } else { + setString(1, StatusUpdate.transient_failure.name) + } + setString(2, msg) + setLong(3, id) execute() } }