[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: Implement balance accounting at Nexus.
From: |
gnunet |
Subject: |
[libeufin] branch master updated: Implement balance accounting at Nexus. |
Date: |
Thu, 02 Sep 2021 23:55:40 +0200 |
This is an automated email from the git hooks/post-receive script.
ms pushed a commit to branch master
in repository libeufin.
The following commit(s) were added to refs/heads/master by this push:
new d61fa04 Implement balance accounting at Nexus.
d61fa04 is described below
commit d61fa04108b0a278b42877b6d9cf70f3d70f8cf3
Author: MS <ms@taler.net>
AuthorDate: Thu Sep 2 21:53:46 2021 +0000
Implement balance accounting at Nexus.
Nexus never calculates balances, but stores the amount as
returned by the bank each time it downloads a "history" message.
The API /bank-accounts/{my-acct} got extended to include the balance.
---
nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt | 14 ++++----
.../tech/libeufin/nexus/bankaccount/BankAccount.kt | 39 ++++++++++++++++++----
.../kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt | 1 -
.../tech/libeufin/nexus/iso20022/Iso20022.kt | 4 +++
.../main/kotlin/tech/libeufin/nexus/server/JSON.kt | 3 ++
.../tech/libeufin/nexus/server/NexusServer.kt | 12 +++++++
6 files changed, 59 insertions(+), 14 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index c42edc9..3469cc9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -113,7 +113,7 @@ class TalerIncomingPaymentEntity(id: EntityID<Long>) :
LongEntity(id) {
}
/**
- * This table logs all the balances as returned by the bank for one particular
bank account.
+ * This table logs all the balances as returned by the bank for all the bank
accounts.
*/
object NexusBankBalancesTable : LongIdTable() {
/**
@@ -123,19 +123,16 @@ object NexusBankBalancesTable : LongIdTable() {
*/
val balance = text("balance") // $currency:x.y
val creditDebitIndicator = text("creditDebitIndicator") // CRDT or DBIT.
- /**
- * Message downloaded from the bank. Must be of "history" type.
- */
- val bankMessage = reference("bankMessage", NexusBankMessagesTable)
val bankAccount = reference("bankAccount", NexusBankAccountsTable)
+ val date = text("date") // in the YYYY-MM-DD format
}
class NexusBankBalanceEntity(id: EntityID<Long>) : LongEntity(id) {
companion object :
LongEntityClass<NexusBankBalanceEntity>(NexusBankBalancesTable)
var balance by NexusBankBalancesTable.balance
var creditDebitIndicator by NexusBankBalancesTable.creditDebitIndicator
- var bankMessage by NexusBankMessageEntity referencedOn
NexusBankBalancesTable.bankMessage
var bankAccount by NexusBankAccountEntity referencedOn
NexusBankBalancesTable.bankAccount
+ var date by NexusBankBalancesTable.date
}
/**
@@ -497,11 +494,13 @@ fun dbDropTables(dbConnectionString: String) {
TalerInvalidIncomingPaymentsTable,
NexusBankConnectionsTable,
NexusBankMessagesTable,
+ NexusBankBalancesTable,
FacadesTable,
FacadeStateTable,
NexusScheduledTasksTable,
OfferedBankAccountsTable,
NexusPermissionsTable,
+ AnastasisIncomingPaymentsTable
)
}
}
@@ -516,6 +515,7 @@ fun dbCreateTables(dbConnectionString: String) {
PaymentInitiationsTable,
NexusEbicsSubscribersTable,
NexusBankAccountsTable,
+ NexusBankBalancesTable,
NexusBankTransactionsTable,
AnastasisIncomingPaymentsTable,
TalerIncomingPaymentsTable,
@@ -526,7 +526,7 @@ fun dbCreateTables(dbConnectionString: String) {
NexusBankMessagesTable,
FacadesTable,
OfferedBankAccountsTable,
- NexusPermissionsTable,
+ NexusPermissionsTable
)
}
}
diff --git
a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
index 2b7c3bd..8528161 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -33,6 +33,7 @@ import tech.libeufin.nexus.iso20022.parseCamtMessage
import tech.libeufin.nexus.server.FetchSpecJson
import tech.libeufin.nexus.server.Pain001Data
import tech.libeufin.nexus.server.requireBankConnection
+import tech.libeufin.nexus.server.toPlainString
import tech.libeufin.util.XMLUtil
import java.time.Instant
import java.time.ZonedDateTime
@@ -127,7 +128,7 @@ private fun findDuplicate(bankAccountId: String,
acctSvcrRef: String): NexusBank
* NOTE: this type can be used BOTH for one Camt document OR
* for a set of those.
*/
-data class CamtProcessingResult(
+data class CamtTransactionsCount(
/**
* Number of transactions that are new to the database.
* Note that transaction T can be downloaded multiple times;
@@ -143,7 +144,10 @@ data class CamtProcessingResult(
*/
val downloadedTransactions: Int
)
-fun processCamtMessage(bankAccountId: String, camtDoc: Document, code:
String): CamtProcessingResult {
+
+fun processCamtMessage(
+ bankAccountId: String, camtDoc: Document, code: String
+): CamtTransactionsCount {
logger.info("processing CAMT message")
var newTransactions = 0
var downloadedTransactions = 0
@@ -159,6 +163,29 @@ fun processCamtMessage(bankAccountId: String, camtDoc:
Document, code: String):
newTransactions = -1
return@transaction
}
+ res.reports.forEach {
+ NexusAssert(
+ it.account.iban == acct.iban,
+ "Neuxs hit a report or statement of a wrong IBAN!"
+ )
+ it.balances.forEach { b ->
+ var clbdCount = 0
+ if (b.type == "CLBD") {
+ clbdCount++
+ NexusBankBalanceEntity.new {
+ bankAccount = acct
+ balance = b.amount.toPlainString()
+ creditDebitIndicator = b.creditDebitIndicator.name
+ date = b.date
+ }
+ }
+ if (clbdCount == 0) {
+ logger.warn("The bank didn't return ANY CLBD balances," +
+ " in the message: ${res.messageId}. Please
clarify!")
+ }
+ }
+ }
+
val stamp =
ZonedDateTime.parse(res.creationDateTime,
DateTimeFormatter.ISO_DATE_TIME).toInstant().toEpochMilli()
when (code) {
@@ -226,7 +253,7 @@ fun processCamtMessage(bankAccountId: String, camtDoc:
Document, code: String):
}
}
}
- return CamtProcessingResult(
+ return CamtTransactionsCount(
newTransactions = newTransactions,
downloadedTransactions = downloadedTransactions
)
@@ -236,7 +263,7 @@ fun processCamtMessage(bankAccountId: String, camtDoc:
Document, code: String):
* Create new transactions for an account based on bank messages it
* did not see before.
*/
-fun ingestBankMessagesIntoAccount(bankConnectionId: String, bankAccountId:
String): CamtProcessingResult {
+fun ingestBankMessagesIntoAccount(bankConnectionId: String, bankAccountId:
String): CamtTransactionsCount {
var totalNew = 0
var downloadedTransactions = 0
transaction {
@@ -267,7 +294,7 @@ fun ingestBankMessagesIntoAccount(bankConnectionId: String,
bankAccountId: Strin
acct.highestSeenBankMessageSerialId = lastId
}
// return totalNew
- return CamtProcessingResult(
+ return CamtTransactionsCount(
newTransactions = totalNew,
downloadedTransactions = downloadedTransactions
)
@@ -318,7 +345,7 @@ fun addPaymentInitiation(paymentData: Pain001Data,
debtorAccount: NexusBankAccou
suspend fun fetchBankAccountTransactions(
client: HttpClient, fetchSpec: FetchSpecJson, accountId: String
-): CamtProcessingResult {
+): CamtTransactionsCount {
val res = transaction {
val acct = NexusBankAccountEntity.findByName(accountId)
if (acct == null) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
index 23abfd5..cdc2af9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -70,7 +70,6 @@ private data class EbicsFetchSpec(
val orderParams: EbicsOrderParams
)
-// Moved eventually in a tucked "camt" file.
fun storeCamt(bankConnectionId: String, camt: String, historyType: String) {
val camt53doc = XMLUtil.parseStringIntoDom(camt)
val msgId =
camt53doc.pickStringWithRootNs("/*[1]/*[1]/root:GrpHdr/root:MsgId")
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
index 70bd620..592b7aa 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Iso20022.kt
@@ -110,6 +110,10 @@ data class CamtParseResult(
val messageType: CashManagementResponseType,
val messageId: String,
val creationDateTime: String,
+ /**
+ * One Camt document can contain multiple reports/statements
+ * for each account being owned by the requester.
+ */
val reports: List<CamtReport>
)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
index ef16db6..17db916 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
@@ -441,6 +441,9 @@ data class CurrencyAmount(
val currency: String,
val value: BigDecimal // allows calculations
)
+fun CurrencyAmount.toPlainString(): String {
+ return "${this.currency}:${this.value.toPlainString()}"
+}
data class InitiatedPayments(
val initiatedPayments: MutableList<PaymentStatus> = mutableListOf()
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
index 5bfa62c..12fd7aa 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
@@ -563,9 +563,21 @@ fun serverMain(host: String, port: Int) {
throw NexusError(HttpStatusCode.NotFound, "unknown
bank account")
}
val holderEnc =
URLEncoder.encode(bankAccount.accountHolder, "UTF-8")
+ val lastSeenBalance = NexusBankBalanceEntity.find {
+ NexusBankBalancesTable.bankAccount eq bankAccount.id
+ }.lastOrNull()
return@transaction makeJsonObject {
prop("defaultBankConnection",
bankAccount.defaultBankConnection?.id?.value)
prop("accountPaytoUri",
"payto://iban/${bankAccount.iban}?receiver-name=$holderEnc")
+ prop(
+ "lastSeenBalance",
+ if (lastSeenBalance != null) {
+ val sign = if
(lastSeenBalance.creditDebitIndicator == "DBIT") "-" else ""
+ "${sign}${lastSeenBalance.balance}"
+ } else {
+ "not downloaded from the bank yet"
+ }
+ )
}
}
call.respond(res)
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libeufin] branch master updated: Implement balance accounting at Nexus.,
gnunet <=