gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] 03/03: Nexus database.


From: gnunet
Subject: [libeufin] 03/03: Nexus database.
Date: Tue, 24 Oct 2023 10:57:50 +0200

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

ms pushed a commit to branch master
in repository libeufin.

commit f803d69f428be15486efc58d07eb3b2ee2b0c327
Author: MS <ms@taler.net>
AuthorDate: Tue Oct 24 10:56:54 2023 +0200

    Nexus database.
    
    Creating incoming payments and setting them as submitted.
---
 database-versioning/libeufin-nexus-0001.sql        |  2 +-
 .../main/kotlin/tech/libeufin/nexus/Database.kt    | 81 +++++++++++++++++++++-
 nexus/src/test/kotlin/Common.kt                    | 11 +++
 nexus/src/test/kotlin/DatabaseTest.kt              | 30 +++++++-
 util/src/main/kotlin/DB.kt                         |  2 +-
 5 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/database-versioning/libeufin-nexus-0001.sql 
b/database-versioning/libeufin-nexus-0001.sql
index 97dbb527..003bd423 100644
--- a/database-versioning/libeufin-nexus-0001.sql
+++ b/database-versioning/libeufin-nexus-0001.sql
@@ -58,7 +58,7 @@ CREATE TABLE IF NOT EXISTS initiated_outgoing_transactions
   ,hidden BOOL DEFAULT FALSE -- FIXME: explain this.
   ,client_request_uuid TEXT UNIQUE
   ,failure_message TEXT -- NOTE: that may mix soon failures (those found at 
initiation time), or late failures (those found out along a fetch operation)
-    );
+  );
 
 COMMENT ON COLUMN initiated_outgoing_transactions.outgoing_transaction_id
     IS 'Points to the bank transaction that was found via nexus-fetch.  If 
"submitted" is false or nexus-fetch could not download this initiation, this 
column is expected to be NULL.';
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
index 45558da8..77086257 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
@@ -12,14 +12,28 @@ import java.sql.PreparedStatement
 import java.sql.SQLException
 import java.time.Instant
 
-/* only importing TalerAmount from bank ONCE that Nexus has
-* its httpd component.  */
 data class TalerAmount(
     val value: Long,
     val fraction: Int,
     val currency: String
 )
 
+// INCOMING PAYMENTS STRUCTS
+
+/**
+ * Represents an incoming payment in the database.
+ */
+data class IncomingPayment(
+    val amount: TalerAmount,
+    val wireTransferSubject: String,
+    val debitPaytoUri: String,
+    val executionTime: Instant,
+    val bankTransferId: String,
+    val bounced: Boolean
+)
+
+// INITIATED PAYMENTS STRUCTS
+
 /**
  * Minimal set of information to initiate a new payment in
  * the database.
@@ -97,6 +111,69 @@ class Database(dbConfig: String): java.io.Closeable {
         }
     }
 
+    // INCOMING PAYMENTS METHODS
+
+    /**
+     * Flags an incoming payment as bounced.  NOTE: the flag merely means
+     * that the payment had an invalid subject for a Taler withdrawal _and_
+     * it got sent to the initiated outgoing payments.  In NO way this flag
+     * means that the actual value was returned to the initial debtor.
+     *
+     * FIXME: this needs to run within the same transaction where the payment 
gets initiated.
+     *
+     * @param rowId row ID of the payment to flag as bounced.
+     * @return true on success, false otherwise.
+     */
+    suspend fun incomingPaymentSetAsBounced(rowId: Long): Boolean = runConn { 
conn ->
+        val stmt = conn.prepareStatement("""
+             UPDATE incoming_transactions
+                      SET bounced = true
+                      WHERE incoming_transaction_id=?
+             """
+        )
+        stmt.setLong(1, rowId)
+        return@runConn stmt.maybeUpdate()
+    }
+
+    /**
+     * Creates a new incoming payment record in the database.
+     *
+     * @param paymentData information related to the incoming payment.
+     * @return true on success, false otherwise.
+     */
+    suspend fun incomingPaymentCreate(paymentData: IncomingPayment): Boolean = 
runConn { conn ->
+        val stmt = conn.prepareStatement("""
+            INSERT INTO incoming_transactions (
+              amount
+              ,wire_transfer_subject
+              ,execution_time
+              ,debit_payto_uri
+              ,bank_transfer_id
+              ,bounced
+            ) VALUES (
+              (?,?)::taler_amount
+              ,?
+              ,?
+              ,?
+              ,?
+              ,?
+            )
+        """)
+        stmt.setLong(1, paymentData.amount.value)
+        stmt.setInt(2, paymentData.amount.fraction)
+        stmt.setString(3, paymentData.wireTransferSubject)
+        val executionTime = paymentData.executionTime.toDbMicros() ?: run {
+            throw Exception("Execution time could not be converted to 
microseconds for the database.")
+        }
+        stmt.setLong(4, executionTime)
+        stmt.setString(5, paymentData.debitPaytoUri)
+        stmt.setString(6, paymentData.bankTransferId)
+        stmt.setBoolean(7, paymentData.bounced)
+        return@runConn stmt.maybeUpdate()
+    }
+
+    // INITIATED PAYMENTS METHODS
+
     /**
      * Sets payment initiation as submitted.
      *
diff --git a/nexus/src/test/kotlin/Common.kt b/nexus/src/test/kotlin/Common.kt
index eed13cc1..3e89c854 100644
--- a/nexus/src/test/kotlin/Common.kt
+++ b/nexus/src/test/kotlin/Common.kt
@@ -79,4 +79,15 @@ fun genInitPay(subject: String, rowUuid: String? = null) =
         wireTransferSubject = subject,
         initiationTime = Instant.now(),
         clientRequestUuid = rowUuid
+    )
+
+// Generates an incoming payment, given its subject.
+fun genIncPay(subject: String, rowUuid: String? = null) =
+    IncomingPayment(
+        amount = TalerAmount(44, 0, "KUDOS"),
+        debitPaytoUri = "payto://iban/not-used",
+        wireTransferSubject = subject,
+        executionTime = Instant.now(),
+        bounced = false,
+        bankTransferId = "entropic"
     )
\ No newline at end of file
diff --git a/nexus/src/test/kotlin/DatabaseTest.kt 
b/nexus/src/test/kotlin/DatabaseTest.kt
index 72a04b4e..d5301063 100644
--- a/nexus/src/test/kotlin/DatabaseTest.kt
+++ b/nexus/src/test/kotlin/DatabaseTest.kt
@@ -1,16 +1,41 @@
+import io.ktor.client.*
+import io.ktor.client.request.*
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import tech.libeufin.nexus.InitiatedPayment
 import tech.libeufin.nexus.NEXUS_CONFIG_SOURCE
 import tech.libeufin.nexus.PaymentInitiationOutcome
 import tech.libeufin.nexus.TalerAmount
-import tech.libeufin.util.connectWithSchema
+import tech.libeufin.util.transaction
 import java.time.Instant
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
 import kotlin.test.assertTrue
 
-class DatabaseTest {
+class IncomingPaymentsTest {
+    // Tests the creation of an incoming payment.
+    @Test
+    fun incomingPaymentCreation() {
+        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val countRows = "SELECT count(*) AS how_many FROM 
incoming_transactions"
+        runBlocking {
+            // Asserting the table is empty.
+            db.runConn {
+                val res = it.execSQLQuery(countRows)
+                assertTrue(res.next())
+                assertEquals(0, res.getInt("how_many"))
+            }
+            db.incomingPaymentCreate(genIncPay("singleton"))
+            // Asserting the table has one.
+            db.runConn {
+                val res = it.execSQLQuery(countRows)
+                assertTrue(res.next())
+                assertEquals(1, res.getInt("how_many"))
+            }
+        }
+    }
+}
+class PaymentInitiationsTest {
     // Tests the flagging of payments as submitted.
     @Test
     fun paymentInitiationSetAsSubmitted() {
@@ -34,7 +59,6 @@ class DatabaseTest {
             }
             // Switching the submitted state to true.
             assertTrue(db.initiatedPaymentSetSubmitted(1))
-
             // Asserting on the submitted state being TRUE now.
             db.runConn { conn ->
                 val isSubmitted = conn.execSQLQuery(getRowOne)
diff --git a/util/src/main/kotlin/DB.kt b/util/src/main/kotlin/DB.kt
index 2966880a..3e0b55fe 100644
--- a/util/src/main/kotlin/DB.kt
+++ b/util/src/main/kotlin/DB.kt
@@ -345,6 +345,7 @@ fun pgDataSource(dbConfig: String): PGSimpleDataSource {
 
 fun PGSimpleDataSource.pgConnection(): PgConnection {
     val conn = connection.unwrap(PgConnection::class.java)
+    // FIXME: bring the DB schema to a function argument.
     conn.execSQLUpdate("SET search_path TO libeufin_bank;")
     return conn
 }
@@ -401,7 +402,6 @@ fun initializeDatabaseTables(cfg: DatabaseConfig, 
sqlFilePrefix: String) {
                 conn.execSQLUpdate(sqlPatchText)
             }
             val sqlProcedures = File("${cfg.sqlDir}/procedures.sql")
-            // Nexus doesn't have any procedures.
             if (!sqlProcedures.exists()) {
                 logger.info("No procedures.sql for the SQL collection: 
$sqlFilePrefix")
                 return@transaction

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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