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