merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

lookup_reconciliation_details.c (5856B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2026 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify it under the
      6    terms of the GNU General Public License as published by the Free Software
      7    Foundation; either version 3, or (at your option) any later version.
      8 
      9    TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13    You should have received a copy of the GNU General Public License along with
     14    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 /**
     17  * @file src/backenddb/lookup_reconciliation_details.c
     18  * @brief Implementation of the lookup_reconciliation_details function for Postgres
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"
     22 #include <taler/taler_pq_lib.h>
     23 #include "merchant-database/lookup_reconciliation_details.h"
     24 #include "helper.h"
     25 
     26 
     27 /**
     28  * Context for TALER_MERCHANTDB_lookup_reconciliation_details().
     29  */
     30 struct ReconciliationContext
     31 {
     32   /**
     33    * Function to call with the results.
     34    */
     35   TALER_MERCHANTDB_ReconciliationDetailsCallback cb;
     36 
     37   /**
     38    * Closure for @e cb.
     39    */
     40   void *cb_cls;
     41 
     42   /**
     43    * Database context.
     44    */
     45   struct TALER_MERCHANTDB_PostgresContext *pg;
     46 
     47   /**
     48    * Set to the return value on errors.
     49    */
     50   enum GNUNET_DB_QueryStatus qs;
     51 
     52 };
     53 
     54 
     55 /**
     56  * Function to be called with the results of a SELECT statement
     57  * that has returned @a num_results results about reconciliation
     58  * details.
     59  *
     60  * @param cls of type `struct ReconciliationContext *`
     61  * @param result the postgres result
     62  * @param num_results the number of results in @a result
     63  */
     64 static void
     65 reconciliation_cb (void *cls,
     66                    PGresult *result,
     67                    unsigned int num_results)
     68 {
     69   struct ReconciliationContext *lic = cls;
     70 
     71   for (unsigned int i = 0; i < num_results; i++)
     72   {
     73     char *order_id;
     74     uint64_t dvs;
     75     uint64_t dfs;
     76     uint64_t fvs;
     77     uint64_t ffs;
     78     char *currency;
     79     struct TALER_Amount remaining_deposit;
     80     struct TALER_Amount deposit_fee;
     81     struct GNUNET_PQ_ResultSpec rs[] = {
     82       GNUNET_PQ_result_spec_string ("order_id",
     83                                     &order_id),
     84       GNUNET_PQ_result_spec_string ("currency",
     85                                     &currency),
     86       GNUNET_PQ_result_spec_uint64 ("deposit_value_sum",
     87                                     &dvs),
     88       GNUNET_PQ_result_spec_uint64 ("deposit_frac_sum",
     89                                     &dfs),
     90       GNUNET_PQ_result_spec_uint64 ("fee_value_sum",
     91                                     &fvs),
     92       GNUNET_PQ_result_spec_uint64 ("fee_frac_sum",
     93                                     &ffs),
     94       GNUNET_PQ_result_spec_end
     95     };
     96 
     97     if (GNUNET_OK !=
     98         GNUNET_PQ_extract_result (result,
     99                                   rs,
    100                                   i))
    101     {
    102       GNUNET_break (0);
    103       lic->qs = GNUNET_DB_STATUS_HARD_ERROR;
    104       return;
    105     }
    106     GNUNET_assert (GNUNET_OK ==
    107                    TALER_amount_set_zero (currency,
    108                                           &remaining_deposit));
    109     GNUNET_assert (GNUNET_OK ==
    110                    TALER_amount_set_zero (currency,
    111                                           &deposit_fee));
    112     remaining_deposit.value = dvs + dfs / TALER_AMOUNT_FRAC_BASE;
    113     remaining_deposit.fraction = dfs % TALER_AMOUNT_FRAC_BASE;
    114     deposit_fee.value = fvs + ffs / TALER_AMOUNT_FRAC_BASE;
    115     deposit_fee.fraction = ffs % TALER_AMOUNT_FRAC_BASE;
    116 
    117     lic->cb (lic->cb_cls,
    118              order_id,
    119              &remaining_deposit,
    120              &deposit_fee);
    121     GNUNET_PQ_cleanup_result (rs);
    122   }
    123 }
    124 
    125 
    126 enum GNUNET_DB_QueryStatus
    127 TALER_MERCHANTDB_lookup_reconciliation_details (
    128   struct TALER_MERCHANTDB_PostgresContext *pg,
    129   const char *instance_id,
    130   uint64_t expected_incoming_serial,
    131   TALER_MERCHANTDB_ReconciliationDetailsCallback cb,
    132   void *cb_cls)
    133 {
    134   struct ReconciliationContext lic = {
    135     .cb = cb,
    136     .cb_cls = cb_cls,
    137     .pg = pg
    138   };
    139   struct GNUNET_PQ_QueryParam params[] = {
    140     GNUNET_PQ_query_param_uint64 (&expected_incoming_serial),
    141     GNUNET_PQ_query_param_end
    142   };
    143   enum GNUNET_DB_QueryStatus qs;
    144 
    145   GNUNET_assert (NULL != pg->current_merchant_id);
    146   GNUNET_assert (0 == strcmp (instance_id,
    147                               pg->current_merchant_id));
    148   check_connection (pg);
    149   TMH_PQ_prepare_anon (pg,
    150                        "SELECT"
    151                        " mct.order_id"
    152                        ",SUM((etc.exchange_deposit_value).val)::INT8 AS deposit_value_sum"
    153                        ",SUM((etc.exchange_deposit_value).frac)::INT8 AS deposit_frac_sum"
    154                        ",SUM((etc.exchange_deposit_fee).val)::INT8 AS fee_value_sum"
    155                        ",SUM((etc.exchange_deposit_fee).frac)::INT8 AS fee_frac_sum"
    156                        ",(etc.exchange_deposit_value).curr AS currency"
    157                        " FROM merchant_expected_transfer_to_coin etc"
    158                        " JOIN merchant_deposits md"
    159                        "   USING (deposit_serial)"
    160                        " JOIN merchant_deposit_confirmations mdc"
    161                        "   USING (deposit_confirmation_serial)"
    162                        " JOIN merchant_contract_terms mct"
    163                        "   USING (order_serial)"
    164                        " WHERE expected_credit_serial=$1"
    165                        " GROUP BY mct.order_id, (etc.exchange_deposit_value).curr;");
    166   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    167                                              "",
    168                                              params,
    169                                              &reconciliation_cb,
    170                                              &lic);
    171   if (0 > lic.qs)
    172     return lic.qs;
    173   return qs;
    174 }