lookup_transfer_details_by_order.c (8004B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2023, 2025, 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_transfer_details_by_order.c 18 * @brief Implementation of the lookup_transfer_details_by_order function for Postgres 19 * @author Iván Ávalos 20 */ 21 #include "platform.h" 22 #include <taler/taler_error_codes.h> 23 #include <taler/taler_dbevents.h> 24 #include <taler/taler_pq_lib.h> 25 #include "merchant-database/lookup_transfer_details_by_order.h" 26 #include "helper.h" 27 28 /** 29 * Closure for lookup_transfer_details_by_order_cb(). 30 */ 31 struct LookupTransferDetailsByOrderContext 32 { 33 34 /** 35 * Plugin context. 36 */ 37 struct TALER_MERCHANTDB_PostgresContext *pg; 38 39 /** 40 * Function to call with all results. 41 */ 42 TALER_MERCHANTDB_OrderTransferDetailsCallback cb; 43 44 /** 45 * Closure for @e cb. 46 */ 47 void *cb_cls; 48 49 /** 50 * Set to the query result. 51 */ 52 enum GNUNET_DB_QueryStatus qs; 53 }; 54 55 56 /** 57 * Function to be called with the results of a SELECT statement 58 * that has returned @a num_results results. We SELECT by coin, 59 * but because that's not useful for the UI, we combine all coins 60 * that were deposited in the same wire transfer into a single 61 * record before calling the callback. 62 * 63 * @param cls of type `struct LookupTransferDetailsByOrderContext *` 64 * @param result the postgres result 65 * @param num_results the number of results in @a result 66 */ 67 static void 68 lookup_transfer_details_by_order_cb (void *cls, 69 PGresult *result, 70 unsigned int num_results) 71 { 72 struct LookupTransferDetailsByOrderContext *ltdo = cls; 73 struct TALER_WireTransferIdentifierRawP last_wtid; 74 char *last_exchange_url = NULL; 75 struct GNUNET_TIME_Timestamp last_execution_time; 76 struct TALER_Amount last_deposit_value; 77 struct TALER_Amount last_deposit_fee; 78 bool last_confirmed; 79 uint64_t last_expected_credit_serial; 80 81 for (unsigned int i = 0; i<num_results; i++) 82 { 83 struct TALER_WireTransferIdentifierRawP wtid; 84 char *exchange_url; 85 struct GNUNET_TIME_Timestamp execution_time; 86 struct TALER_Amount deposit_value; 87 struct TALER_Amount deposit_fee; 88 bool confirmed; 89 uint64_t expected_credit_serial; 90 struct GNUNET_PQ_ResultSpec rs[] = { 91 GNUNET_PQ_result_spec_timestamp ("deposit_timestamp", 92 &execution_time), 93 GNUNET_PQ_result_spec_string ("exchange_url", 94 &exchange_url), 95 GNUNET_PQ_result_spec_bool ("confirmed", 96 &confirmed), 97 GNUNET_PQ_result_spec_auto_from_type ("wtid", 98 &wtid), 99 GNUNET_PQ_result_spec_uint64 ("expected_credit_serial", 100 &expected_credit_serial), 101 TALER_PQ_result_spec_amount_with_currency ("exchange_deposit_value", 102 &deposit_value), 103 TALER_PQ_result_spec_amount_with_currency ("exchange_deposit_fee", 104 &deposit_fee), 105 GNUNET_PQ_result_spec_end 106 }; 107 108 if (GNUNET_OK != 109 GNUNET_PQ_extract_result (result, 110 rs, 111 i)) 112 { 113 GNUNET_break (0); 114 ltdo->qs = GNUNET_DB_STATUS_HARD_ERROR; 115 return; 116 } 117 if (0 == i) 118 { 119 last_wtid = wtid; 120 last_exchange_url = exchange_url; 121 last_execution_time = execution_time; 122 last_deposit_value = deposit_value; 123 last_deposit_fee = deposit_fee; 124 last_confirmed = confirmed; 125 last_expected_credit_serial = expected_credit_serial; 126 continue; 127 } 128 if ( (0 == 129 GNUNET_memcmp (&wtid, 130 &last_wtid)) && 131 (0 == strcmp (exchange_url, 132 last_exchange_url)) && 133 (expected_credit_serial == 134 last_expected_credit_serial) && 135 (GNUNET_TIME_timestamp_cmp (execution_time, 136 ==, 137 last_execution_time)) && 138 (last_confirmed == confirmed) && 139 (GNUNET_OK == 140 TALER_amount_cmp_currency (&deposit_value, 141 &last_deposit_value)) ) 142 { 143 GNUNET_assert (0 <= 144 TALER_amount_add (&last_deposit_value, 145 &last_deposit_value, 146 &deposit_value)); 147 GNUNET_assert (0 <= 148 TALER_amount_add (&last_deposit_fee, 149 &last_deposit_fee, 150 &deposit_fee)); 151 continue; 152 } 153 ltdo->cb (ltdo->cb_cls, 154 &last_wtid, 155 last_exchange_url, 156 last_execution_time, 157 &last_deposit_value, 158 &last_deposit_fee, 159 last_confirmed, 160 last_expected_credit_serial); 161 GNUNET_free (exchange_url); 162 last_wtid = wtid; 163 last_exchange_url = exchange_url; 164 last_execution_time = execution_time; 165 last_deposit_value = deposit_value; 166 last_deposit_fee = deposit_fee; 167 last_confirmed = confirmed; 168 last_expected_credit_serial = expected_credit_serial; 169 } 170 if (num_results > 0) 171 { 172 ltdo->cb (ltdo->cb_cls, 173 &last_wtid, 174 last_exchange_url, 175 last_execution_time, 176 &last_deposit_value, 177 &last_deposit_fee, 178 last_confirmed, 179 last_expected_credit_serial); 180 } 181 GNUNET_free (last_exchange_url); 182 ltdo->qs = num_results; 183 } 184 185 186 enum GNUNET_DB_QueryStatus 187 TALER_MERCHANTDB_lookup_transfer_details_by_order ( 188 struct TALER_MERCHANTDB_PostgresContext *pg, 189 uint64_t order_serial, 190 TALER_MERCHANTDB_OrderTransferDetailsCallback cb, 191 void *cb_cls) 192 { 193 struct LookupTransferDetailsByOrderContext ltdo = { 194 .pg = pg, 195 .cb = cb, 196 .cb_cls = cb_cls 197 }; 198 struct GNUNET_PQ_QueryParam params[] = { 199 GNUNET_PQ_query_param_uint64 (&order_serial), 200 GNUNET_PQ_query_param_end 201 }; 202 enum GNUNET_DB_QueryStatus qs; 203 204 check_connection (pg); 205 PREPARE (pg, 206 "lookup_transfer_details_by_order", 207 "SELECT" 208 " md.deposit_serial" 209 ",mcon.exchange_url" 210 ",met.wtid" 211 ",mtc.exchange_deposit_value" 212 ",mtc.exchange_deposit_fee" 213 ",mcon.deposit_timestamp" 214 ",met.confirmed" 215 ",met.expected_credit_serial" 216 " FROM merchant_expected_transfer_to_coin mtc" 217 " JOIN merchant_deposits md" 218 " USING (deposit_serial)" 219 " JOIN merchant_deposit_confirmations mcon" 220 " USING (deposit_confirmation_serial)" 221 " JOIN merchant_expected_transfers met" 222 " USING (expected_credit_serial)" 223 " JOIN merchant_accounts acc" 224 " ON (acc.account_serial = met.account_serial)" 225 /* Check that all this is for the same instance */ 226 " JOIN merchant_contract_terms contracts" 227 " USING (merchant_serial, order_serial)" 228 " WHERE mcon.order_serial=$1" 229 " ORDER BY met.wtid"); 230 231 qs = GNUNET_PQ_eval_prepared_multi_select ( 232 pg->conn, 233 "lookup_transfer_details_by_order", 234 params, 235 &lookup_transfer_details_by_order_cb, 236 <do); 237 if (qs < 0) 238 return qs; 239 return ltdo.qs; 240 }