gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] branch master updated: Implement refunds, plus helpers.


From: gnunet
Subject: [libeufin] branch master updated: Implement refunds, plus helpers.
Date: Tue, 31 Mar 2020 18:28:00 +0200

This is an automated email from the git hooks/post-receive script.

marcello pushed a commit to branch master
in repository libeufin.

The following commit(s) were added to refs/heads/master by this push:
     new 8723a71  Implement refunds, plus helpers.
8723a71 is described below

commit 8723a7107d0916ded72cdcf311ddc59f6343ecee
Author: Marcello Stanisci <address@hidden>
AuthorDate: Tue Mar 31 18:24:58 2020 +0200

    Implement refunds, plus helpers.
    
    However, the function that calculates the
    refund amount is still WIP as it only echoes
    back the original amount.
---
 nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt    |   8 +-
 .../src/main/kotlin/tech/libeufin/nexus/Helpers.kt |  16 +++
 nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt  | 127 ++++++++++-----------
 util/src/main/kotlin/XMLUtil.kt                    |   4 +
 4 files changed, 85 insertions(+), 70 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index e15b295..361cf6a 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -38,7 +38,10 @@ object EbicsRawBankTransactionsTable : LongIdTable() {
     val currency = text("currency")
     val amount = text("amount")
     val creditorIban = text("creditorIban")
+    val creditorName = text("creditorBic")
     val debitorIban = text("debitorIban")
+    val debitorName = text("debitorName")
+    val counterpartBic = text("counterpartBic")
     val bookingDate = text("bookingDate")
 }
 
@@ -50,8 +53,11 @@ class EbicsRawBankTransactionEntry(id: EntityID<Long>) : 
LongEntity(id) {
     var transactionType by EbicsRawBankTransactionsTable.transactionType
     var currency by EbicsRawBankTransactionsTable.currency
     var amount by EbicsRawBankTransactionsTable.amount
-    var creditorIban by EbicsRawBankTransactionsTable.creditorIban
     var debitorIban by EbicsRawBankTransactionsTable.debitorIban
+    var debitorName by EbicsRawBankTransactionsTable.debitorName
+    var creditorName by EbicsRawBankTransactionsTable.creditorName
+    var creditorIban by EbicsRawBankTransactionsTable.creditorIban
+    var counterpartBic by EbicsRawBankTransactionsTable.counterpartBic
     var bookingDate by EbicsRawBankTransactionsTable.bookingDate
     var nexusSubscriber by EbicsSubscriberEntity referencedOn 
EbicsRawBankTransactionsTable.nexusSubscriber
 }
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
index 468e8f0..e39f521 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
@@ -28,4 +28,20 @@ fun chunkString(input: String): String {
 
 fun expectId(param: String?): String {
     return param ?: throw NexusError(HttpStatusCode.BadRequest, "Bad ID given")
+}
+
+/* Needs a transaction{} block to be called */
+fun expectIdTransaction(param: String?): EbicsSubscriberEntity {
+    if (param == null) {
+        throw NexusError(HttpStatusCode.BadRequest, "Null Id given")
+    }
+    return EbicsSubscriberEntity.findById(param) ?: throw 
NexusError(HttpStatusCode.NotFound, "Subscriber: $param not found")
+}
+
+/* Needs a transaction{} block to be called */
+fun expectAcctidTransaction(param: String?): EbicsAccountInfoEntity {
+    if (param == null) {
+        throw NexusError(HttpStatusCode.BadRequest, "Null Acctid given")
+    }
+    return EbicsAccountInfoEntity.findById(param) ?: throw 
NexusError(HttpStatusCode.NotFound, "Account: $param not found")
 }
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 7f3dae0..81773a8 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -101,18 +101,9 @@ fun getSubscriberEntityFromId(id: String): 
EbicsSubscriberEntity {
     }
 }
 
-fun getBankAccountDetailsFromAcctid(id: String): EbicsAccountInfoElement {
-    return transaction {
-        val bankAccount = EbicsAccountInfoEntity.find {
-            EbicsAccountsInfoTable.id eq id
-        }.firstOrNull() ?: throw NexusError(HttpStatusCode.NotFound, "Bank 
account not found from account id '$id'")
-        EbicsAccountInfoElement(
-            accountId = id,
-            accountHolderName = bankAccount.accountHolder,
-            iban = bankAccount.iban,
-            bankCode = bankAccount.bankCode
-        )
-    }
+fun calculateRefund(amount: String): Amount {
+    // fixme: must apply refund fees!
+    return Amount(amount)
 }
 
 /**
@@ -457,38 +448,34 @@ fun main() {
                 )
                 return@get
             }
-
             /**
              * This endpoint gathers all the data needed to create a payment 
and persists it
              * into the database.  However, it does NOT perform the payment 
itself!
              */
             post("/ebics/subscribers/{id}/accounts/{acctid}/prepare-payment") {
-                val acctid = expectId(call.parameters["acctid"])
-                val subscriberId = expectId(call.parameters["id"])
-
-                transaction {
-                    val accountinfo = EbicsAccountInfoEntity.findById(acctid)  
?: throw NexusError(
-                        HttpStatusCode.NotFound, "Bank account with id 
'$acctid' not found (trigger HTD first?)"
-                    )
-                    val subscriber = 
EbicsSubscriberEntity.findById(subscriberId) ?: throw NexusError(
-                        HttpStatusCode.NotFound, "Subscriber '$subscriberId' 
not found"
-                    )
-                    if (accountinfo.subscriber != subscriber) {
-                        throw NexusError(HttpStatusCode.BadRequest, "Claimed 
bank account '$acctid' doesn't belong to subscriber '$subscriberId'!")
+                val acctid = transaction {
+                    val accountInfo = 
expectAcctidTransaction(call.parameters["acctid"])
+                    val subscriber = 
expectIdTransaction(call.parameters["subscriber"])
+                    if (accountInfo.subscriber != subscriber) {
+                        throw NexusError(
+                            HttpStatusCode.BadRequest,
+                            "Claimed bank account '${accountInfo.id}' doesn't 
belong to subscriber '${subscriber.id}'!"
+                        )
                     }
+                    accountInfo.id.value
                 }
                 val pain001data = call.receive<Pain001Data>()
                 createPain001entry(pain001data, acctid)
-
-                call.respondText("Payment instructions persisted in DB", 
ContentType.Text.Plain, HttpStatusCode.OK)
+                call.respondText(
+                    "Payment instructions persisted in DB",
+                    ContentType.Text.Plain, HttpStatusCode.OK
+                )
                 return@post
             }
-
             /**
              * list all the prepared payments related to customer {id}
              */
             get("/ebics/subscribers/{id}/payments") {
-
                 val id = expectId(call.parameters["id"])
                 val ret = PaymentsInfo()
                 transaction {
@@ -552,7 +539,6 @@ fun main() {
                 )
                 return@post
             }
-
             /**
              * This function triggers the Nexus to perform all those 
un-submitted payments.
              * Ideally, this logic will be moved into some more automatic 
mechanism.
@@ -643,12 +629,40 @@ fun main() {
 
                 return@get
             }
+
+            post("/ebics/taler/{id}/{acctid}/refund-invalid-payments") {
+                transaction {
+                    val subscriber = expectIdTransaction(call.parameters["id"])
+                    val acctid = 
expectAcctidTransaction(call.parameters["acctid"])
+                    if (acctid.subscriber.id != subscriber.id) {
+                        throw NexusError(
+                            HttpStatusCode.Forbidden,
+                            "Such subscriber (${subscriber.id}) can't drive 
such account (${acctid.id})"
+                        )
+                    }
+                    TalerIncomingPaymentEntry.find {
+                        TalerIncomingPayments.processed eq false
+                    }.forEach {
+                        createPain001entry(
+                            Pain001Data(
+                                creditorName = it.payment.debitorName,
+                                creditorIban = it.payment.debitorIban,
+                                creditorBic = it.payment.counterpartBic,
+                                sum = calculateRefund(it.payment.amount),
+                                subject = "Taler refund"
+                            ),
+                            acctid.id.value
+                        )
+                    }
+                }
+                return@post
+            }
             /**
              * VERY taler-related behaviour, where the Nexus differentiates 
good
              * incoming transactions (those with a valid subject, i.e. a 
public key),
              * and invalid ones (the rest).
              */
-            post("/ebics/subscribers/{id}/digest-incoming-transactions") {
+            post("/ebics/taler/{id}/digest-incoming-transactions") {
                 val id = expectId(call.parameters["id"])
                 // first find highest ID value of already processed rows.
                 transaction {
@@ -706,47 +720,23 @@ fun main() {
                         response.orderData.unzipWithLoop {
                             val fileName = it.first
                             val camt53doc = 
XMLUtil.parseStringIntoDom(it.second)
-
-                            val creditorIban = XMLUtil.getStringFromXpath(
-                                camt53doc,
-                                
"//*[local-name()='CdtrAcct']//*[local-name()='IBAN']"
-                            )
-                            val debitorIban = XMLUtil.getStringFromXpath(
-                                camt53doc,
-                                
"//*[local-name()='DbtrAcct']//*[local-name()='IBAN']"
-                            )
-                            val creditOrDebit = XMLUtil.getStringFromXpath(
-                                camt53doc,
-                                
"//*[local-name()='Ntry']//*[local-name()='CdtDbtInd']"
-                            )
-                            val amount = XMLUtil.getStringFromXpath(
-                                camt53doc,
-                                
"//*[local-name()='Ntry']//*[local-name()='Amt']"
-                            )
-                            val bookingDate = XMLUtil.getStringFromXpath(
-                                camt53doc,
-                                
"//*[local-name()='BookgDt']//*[local-name()='Dt']"
-                            )
-                            val subject = XMLUtil.getStringFromXpath(
-                                camt53doc,
-                                
"//*[local-name()='RmtInf']//*[local-name()='Ustrd']"
-                            )
-                            val currency = XMLUtil.getStringFromXpath(
-                                camt53doc,
-                                
"//*[local-name()='Ntry']//*[local-name()='Amt']/@Ccy"
-                            )
                             transaction {
                                 EbicsRawBankTransactionEntry.new {
                                     sourceType = "C53"
                                     sourceFileName = fileName
-                                    unstructuredRemittanceInformation = subject
-                                    transactionType = creditOrDebit
-                                    this.currency = currency
-                                    this.amount = amount
-                                    this.creditorIban = creditorIban
-                                    this.debitorIban = debitorIban
-                                    this.bookingDate = bookingDate
+                                    unstructuredRemittanceInformation = 
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']/@Ccy")
+                                    transactionType = 
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='CdtDbtInd']")
+                                    currency = 
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']/@Ccy")
+                                    amount = 
camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']")
+                                    bookingDate = 
camt53doc.pickString("//*[local-name()='BookgDt']//*[local-name()='Dt']")
                                     nexusSubscriber = 
getSubscriberEntityFromId(id)
+                                    creditorName =
+                                        
camt53doc.pickString("//*[local-name()='RltdPties']//*[local-name()='Dbtr']//*[local-name()='Nm']")
+                                    creditorIban =
+                                        
camt53doc.pickString("//*[local-name()='CdtrAcct']//*[local-name()='IBAN']")
+                                    debitorName = 
camt53doc.pickString("//*[local-name()='RltdPties']//*[local-name()='Dbtr']//*[local-name()='Nm']")
+                                    debitorIban = 
camt53doc.pickString("//*[local-name()='DbtrAcct']//*[local-name()='IBAN']")
+                                    counterpartBic = 
camt53doc.pickString("//*[local-name()='RltdAgts']//*[local-name()='BIC']")
                                 }
                             }
                         }
@@ -763,9 +753,8 @@ fun main() {
                         )
                     }
                 }
-
+                return@post
             }
-
             post("/ebics/subscribers/{id}/collect-transactions-c54") {
                 // FIXME(florian): Download C54 and store the result in the 
right database table
             }
diff --git a/util/src/main/kotlin/XMLUtil.kt b/util/src/main/kotlin/XMLUtil.kt
index 273660f..2889a80 100644
--- a/util/src/main/kotlin/XMLUtil.kt
+++ b/util/src/main/kotlin/XMLUtil.kt
@@ -423,3 +423,7 @@ class XMLUtil private constructor() {
         }
     }
 }
+
+fun Document.pickString(xpath: String): String {
+    return XMLUtil.getStringFromXpath(this, xpath)
+}

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]