gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated: Nexus DB.


From: gnunet
Subject: [libeufin] branch master updated: Nexus DB.
Date: Wed, 25 Oct 2023 09:44:29 +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 b5f49fe4 Nexus DB.
b5f49fe4 is described below

commit b5f49fe4dc38c8e4f818fc45eba7e1264160f581
Author: MS <ms@taler.net>
AuthorDate: Wed Oct 25 09:42:18 2023 +0200

    Nexus DB.
    
    Method to create one incoming transaction, bounce it,
    and finally create its related initiated outgoing payment
    for the reimbursement.
---
 database-versioning/libeufin-nexus-procedures.sql  | 47 ++++++++++++++++-
 .../main/kotlin/tech/libeufin/nexus/Database.kt    | 60 +++++++++++++++++++---
 nexus/src/test/kotlin/Common.kt                    |  1 -
 nexus/src/test/kotlin/DatabaseTest.kt              | 26 ++++++++++
 4 files changed, 125 insertions(+), 9 deletions(-)

diff --git a/database-versioning/libeufin-nexus-procedures.sql 
b/database-versioning/libeufin-nexus-procedures.sql
index b6150cec..d9e547cd 100644
--- a/database-versioning/libeufin-nexus-procedures.sql
+++ b/database-versioning/libeufin-nexus-procedures.sql
@@ -1,7 +1,50 @@
 BEGIN;
 SET search_path TO libeufin_nexus;
 
-CREATE OR REPLACE FUNCTION create_outgoing_tx(
+CREATE OR REPLACE FUNCTION create_incoming_and_bounce(
+  IN in_amount taler_amount
+  ,IN in_wire_transfer_subject TEXT
+  ,IN in_execution_time BIGINT
+  ,IN in_debit_payto_uri TEXT
+  ,IN in_bank_transfer_id TEXT
+  ,IN in_timestamp BIGINT
+) RETURNS void
+LANGUAGE plpgsql AS $$
+BEGIN
+-- creating the bounced incoming transaction.
+INSERT INTO incoming_transactions (
+  amount
+  ,wire_transfer_subject
+  ,execution_time
+  ,debit_payto_uri
+  ,bank_transfer_id
+  ,bounced
+  ) VALUES (
+    in_amount
+    ,in_wire_transfer_subject
+    ,in_execution_time
+    ,in_debit_payto_uri
+    ,in_bank_transfer_id
+    ,true
+  );
+-- creating its reimbursement.
+INSERT INTO initiated_outgoing_transactions (
+  amount
+  ,wire_transfer_subject
+  ,credit_payto_uri
+  ,initiation_time
+  ) VALUES (
+    in_amount
+    ,'refund: ' || in_wire_transfer_subject
+    ,in_debit_payto_uri
+    ,in_timestamp
+  );
+END $$;
+
+COMMENT ON FUNCTION create_incoming_and_bounce(taler_amount, TEXT, BIGINT, 
TEXT, TEXT, BIGINT)
+  IS 'creates one incoming transaction with a bounced state and initiates its 
related refund.';
+
+CREATE OR REPLACE FUNCTION create_outgoing_payment(
   IN in_amount taler_amount
   ,IN in_wire_transfer_subject TEXT
   ,IN in_execution_time BIGINT
@@ -51,7 +94,7 @@ THEN
 END IF;
 END $$;
 
-COMMENT ON FUNCTION create_outgoing_tx(taler_amount, TEXT, BIGINT, TEXT, TEXT, 
BIGINT)
+COMMENT ON FUNCTION create_outgoing_payment(taler_amount, TEXT, BIGINT, TEXT, 
TEXT, BIGINT)
   IS 'Creates a new outgoing payment and optionally reconciles the related 
initiated payment with it.  If the initiated payment to reconcile is not found, 
it inserts NOTHING.';
 
 CREATE OR REPLACE FUNCTION bounce_payment(
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
index 50242e8c..d6ad81fa 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Database.kt
@@ -28,8 +28,7 @@ data class IncomingPayment(
     val wireTransferSubject: String?,
     val debitPaytoUri: String,
     val executionTime: Instant,
-    val bankTransferId: String,
-    val bounced: Boolean
+    val bankTransferId: String
 )
 
 // INITIATED PAYMENTS STRUCTS
@@ -51,8 +50,18 @@ data class InitiatedPayment(
  * into the database.
  */
 enum class PaymentInitiationOutcome {
+    /**
+     * The Payto address to send the payment to was invalid.
+     */
     BAD_CREDIT_PAYTO,
+    /**
+     * The row contains a client_request_uid that exists
+     * already in the database.
+     */
     UNIQUE_CONSTRAINT_VIOLATION,
+    /**
+     * Record successfully created.
+     */
     SUCCESS
 }
 
@@ -71,7 +80,18 @@ data class OutgoingPayment(
  * payment into the database.
  */
 enum class OutgoingPaymentOutcome {
+    /**
+     * The caller wanted to link a previously initiated payment
+     * to this outgoing one, but the row ID passed to the inserting
+     * function could not be found in the payment initiations table.
+     * Note: NO insertion takes place in this case.
+     */
     INITIATED_COUNTERPART_NOT_FOUND,
+    /**
+     * The outgoing payment got inserted and _in case_ the caller
+     * wanted to link a previously initiated payment to this one, that
+     * succeeded too.
+     */
     SUCCESS
 }
 
@@ -148,7 +168,7 @@ class Database(dbConfig: String): java.io.Closeable {
     ): OutgoingPaymentOutcome = runConn {
         val stmt = it.prepareStatement("""
             SELECT out_nx_initiated
-              FROM create_outgoing_tx(
+              FROM create_outgoing_payment(
                 (?,?)::taler_amount
                 ,?
                 ,?
@@ -205,6 +225,37 @@ class Database(dbConfig: String): java.io.Closeable {
         }
     }
 
+    /**
+     * Creates an incoming payment as bounced _and_ initiates its
+     * reimbursement.  Throws exception on unique constraint violation,
+     * or other errors.
+     *
+     * @param paymentData information related to the incoming payment.
+     */
+    suspend fun incomingPaymentCreateBounced(paymentData: IncomingPayment) = 
runConn { conn ->
+        val refundTimestamp = Instant.now().toDbMicros()
+            ?: throw Exception("Could not convert refund execution time from 
Instant.now() to microsends.")
+        val executionTime = paymentData.executionTime.toDbMicros()
+            ?: throw Exception("Could not convert payment execution time from 
Instant to microseconds.")
+        val stmt = conn.prepareStatement("""
+            SELECT create_incoming_and_bounce (
+              (?,?)::taler_amount
+              ,?
+              ,?
+              ,?
+              ,?
+              ,?
+            )""")
+        stmt.setLong(1, paymentData.amount.value)
+        stmt.setInt(2, paymentData.amount.fraction)
+        stmt.setString(3, paymentData.wireTransferSubject)
+        stmt.setLong(4, executionTime)
+        stmt.setString(5, paymentData.debitPaytoUri)
+        stmt.setString(6, paymentData.bankTransferId)
+        stmt.setLong(7, refundTimestamp)
+        stmt.executeQuery()
+    }
+
     /**
      * Creates a new incoming payment record in the database.
      *
@@ -219,14 +270,12 @@ class Database(dbConfig: String): java.io.Closeable {
               ,execution_time
               ,debit_payto_uri
               ,bank_transfer_id
-              ,bounced
             ) VALUES (
               (?,?)::taler_amount
               ,?
               ,?
               ,?
               ,?
-              ,?
             )
         """)
         stmt.setLong(1, paymentData.amount.value)
@@ -238,7 +287,6 @@ class Database(dbConfig: String): java.io.Closeable {
         stmt.setLong(4, executionTime)
         stmt.setString(5, paymentData.debitPaytoUri)
         stmt.setString(6, paymentData.bankTransferId)
-        stmt.setBoolean(7, paymentData.bounced)
         return@runConn stmt.maybeUpdate()
     }
 
diff --git a/nexus/src/test/kotlin/Common.kt b/nexus/src/test/kotlin/Common.kt
index fe4bdcd2..c8f88fca 100644
--- a/nexus/src/test/kotlin/Common.kt
+++ b/nexus/src/test/kotlin/Common.kt
@@ -88,7 +88,6 @@ fun genIncPay(subject: String? = null, rowUuid: String? = 
null) =
         debitPaytoUri = "payto://iban/not-used",
         wireTransferSubject = subject,
         executionTime = Instant.now(),
-        bounced = false,
         bankTransferId = "entropic"
     )
 
diff --git a/nexus/src/test/kotlin/DatabaseTest.kt 
b/nexus/src/test/kotlin/DatabaseTest.kt
index d2a2a92d..9aedb99a 100644
--- a/nexus/src/test/kotlin/DatabaseTest.kt
+++ b/nexus/src/test/kotlin/DatabaseTest.kt
@@ -43,6 +43,32 @@ class OutgoingPaymentsTest {
 }
 
 class IncomingPaymentsTest {
+    // Tests creating and bouncing incoming payments in one DB transaction.
+    @Test
+    fun incomingAndBounce() {
+        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        runBlocking {
+            // creating and bouncing one incoming transaction.
+            db.incomingPaymentCreateBounced(genIncPay("incoming and bounced"))
+            db.runConn {
+                // check the bounced flaag is true
+                val checkBounced = it.prepareStatement("""
+                    SELECT bounced FROM incoming_transactions WHERE 
incoming_transaction_id = 1;
+                """).executeQuery()
+                assertTrue(checkBounced.next())
+                assertTrue(checkBounced.getBoolean("bounced"))
+                // check the related initiated payment exists.
+                val checkInitiated = it.prepareStatement("""
+                    SELECT 
+                      COUNT(initiated_outgoing_transaction_id) AS how_many
+                      FROM initiated_outgoing_transactions
+                """).executeQuery()
+                assertTrue(checkInitiated.next())
+                assertEquals(1, checkInitiated.getInt("how_many"))
+            }
+        }
+    }
+
     // Tests the function that flags incoming payments as bounced.
     @Test
     fun incomingPaymentBounce() {

-- 
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]