libeufin

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

commit 883b422d3b372956d01bd93ae3916fa7afacbdfa
parent 3d38addd545466e8d390e57611aeb1def8e6ad2a
Author: MS <ms@taler.net>
Date:   Wed, 17 Jun 2020 21:32:10 +0200

TWG: fixing outgoing payment ids.

Diffstat:
Mnexus/src/main/kotlin/tech/libeufin/nexus/DB.kt | 24+++++++++---------------
Mnexus/src/main/kotlin/tech/libeufin/nexus/taler.kt | 24+++++++++++++++++++-----
2 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt @@ -41,36 +41,28 @@ import java.sql.Connection * in the PAIN-table. */ object TalerRequestedPayments : LongIdTable() { + // this id gets assigned when the bank confirms the + // corresponding outgoing payment. It is "abstract" + // in the sense that a "early" prepared payment might + // get a "high" id because the bank confirmed it "late". + val abstractId = long("abstractId").nullable() val preparedPayment = reference("payment", InitiatedPaymentsTable) val requestUId = text("request_uid") - - /** - * Amount in the Taler amount format. - */ val amount = text("amount") val exchangeBaseUrl = text("exchange_base_url") val wtid = text("wtid") val creditAccount = text("credit_account") - - /** - * This column gets a value only after the bank acknowledges the payment via - * a camt.05x entry. The "crunch" logic is responsible for assigning such value. - * - * FIXME(dold): Shouldn't this happen at the level of the PreparedPaymentsTable? - */ - val rawConfirmed = reference("raw_confirmed", RawBankTransactionsTable).nullable() } class TalerRequestedPaymentEntity(id: EntityID<Long>) : LongEntity(id) { companion object : LongEntityClass<TalerRequestedPaymentEntity>(TalerRequestedPayments) - + var abstractId by TalerRequestedPayments.abstractId var preparedPayment by InitiatedPaymentEntity referencedOn TalerRequestedPayments.preparedPayment var requestUId by TalerRequestedPayments.requestUId var amount by TalerRequestedPayments.amount var exchangeBaseUrl by TalerRequestedPayments.exchangeBaseUrl var wtid by TalerRequestedPayments.wtid var creditAccount by TalerRequestedPayments.creditAccount - var rawConfirmed by RawBankTransactionEntity optionalReferencedOn TalerRequestedPayments.rawConfirmed } /** @@ -162,7 +154,6 @@ object RawBankTransactionsTable : LongIdTable() { class RawBankTransactionEntity(id: EntityID<Long>) : LongEntity(id) { companion object : LongEntityClass<RawBankTransactionEntity>(RawBankTransactionsTable) - var currency by RawBankTransactionsTable.currency var amount by RawBankTransactionsTable.amount var status by RawBankTransactionsTable.status @@ -319,7 +310,9 @@ object TalerFacadeStateTable : IntIdTable() { val reserveTransferLevel = text("reserveTransferLevel") val intervalIncrement = text("intervalIncrement") val facade = reference("facade", FacadesTable) + // highest ID seen in the raw transactions table. val highestSeenMsgID = long("highestSeenMsgID").default(0) + val highestOutgoingAbstractID = long("highestOutgoingAbstractID").default(0) } class TalerFacadeStateEntity(id: EntityID<Int>) : IntEntity(id) { @@ -333,6 +326,7 @@ class TalerFacadeStateEntity(id: EntityID<Int>) : IntEntity(id) { var intervalIncrement by TalerFacadeStateTable.intervalIncrement var facade by FacadeEntity referencedOn TalerFacadeStateTable.facade var highestSeenMsgID by TalerFacadeStateTable.highestSeenMsgID + var highestOutgoingAbstractID by TalerFacadeStateTable.highestOutgoingAbstractID } fun dbCreateTables(dbName: String) { diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt @@ -479,7 +479,9 @@ private fun ingestIncoming(payment: RawBankTransactionEntity, txDtls: Transactio return } -private fun ingestOutgoing(payment: RawBankTransactionEntity, txDtls: TransactionDetails) { +private fun ingestOutgoing( + txDtls: TransactionDetails, + fcid: String) { val subject = txDtls.unstructuredRemittanceInformation logger.debug("Ingesting outgoing payment: subject") val wtid = extractWtidFromSubject(subject) @@ -495,7 +497,9 @@ private fun ingestOutgoing(payment: RawBankTransactionEntity, txDtls: Transactio return } logger.debug("Payment: ${subject} was requested, and gets now marked as 'confirmed'") - talerRequested.rawConfirmed = payment + val fs = getTalerFacadeState(fcid) + fs.highestOutgoingAbstractID++ + talerRequested.abstractId = fs.highestOutgoingAbstractID } /** @@ -526,7 +530,9 @@ fun ingestTalerTransactions() { logger.warn("batch transactions not supported") } else { when (tx.creditDebitIndicator) { - CreditDebitIndicator.DBIT -> ingestOutgoing(it, txDtls = tx.details[0]) + CreditDebitIndicator.DBIT -> ingestOutgoing( + txDtls = tx.details[0], fcid = facade.id.value + ) CreditDebitIndicator.CRDT -> ingestIncoming(it, txDtls = tx.details[0]) } } @@ -564,9 +570,17 @@ private suspend fun historyOutgoing(call: ApplicationCall) { /** Retrieve all the outgoing payments from the _clean Taler outgoing table_ */ val subscriberBankAccount = getTalerFacadeBankAccount(expectNonNull(call.parameters["fcid"])) - val reqPayments = TalerRequestedPaymentEntity.find { - TalerRequestedPayments.rawConfirmed.isNotNull() and startCmpOp + val reqPayments = mutableListOf<TalerRequestedPaymentEntity>() + val reqPaymentsWithUnconfirmed = TalerRequestedPaymentEntity.find { + if (delta < 0) { + TalerRequestedPayments.abstractId less start + } else TalerRequestedPayments.abstractId greater start }.orderTaler(delta) + reqPaymentsWithUnconfirmed.forEach { + if (it.preparedPayment.rawConfirmation != null) { + reqPayments.add(it) + } + } if (reqPayments.isNotEmpty()) { reqPayments.subList(0, min(abs(delta), reqPayments.size)).forEach { history.outgoing_transactions.add(