Line data Source code
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/iterate_transfer_details_by_order.c
18 : * @brief Implementation of the iterate_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/iterate_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 45 : lookup_transfer_details_by_order_cb (void *cls,
67 : PGresult *result,
68 : unsigned int num_results)
69 : {
70 45 : struct LookupTransferDetailsByOrderContext *ltdo = cls;
71 : struct TALER_WireTransferIdentifierRawP last_wtid;
72 45 : 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 60 : 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 15 : struct GNUNET_PQ_ResultSpec rs[] = {
89 15 : GNUNET_PQ_result_spec_timestamp ("deposit_timestamp",
90 : &execution_time),
91 15 : GNUNET_PQ_result_spec_string ("exchange_url",
92 : &exchange_url),
93 15 : GNUNET_PQ_result_spec_bool ("confirmed",
94 : &confirmed),
95 15 : GNUNET_PQ_result_spec_auto_from_type ("wtid",
96 : &wtid),
97 15 : GNUNET_PQ_result_spec_uint64 ("expected_credit_serial",
98 : &expected_credit_serial),
99 15 : TALER_PQ_result_spec_amount_with_currency ("exchange_deposit_value",
100 : &deposit_value),
101 15 : TALER_PQ_result_spec_amount_with_currency ("exchange_deposit_fee",
102 : &deposit_fee),
103 : GNUNET_PQ_result_spec_end
104 : };
105 :
106 15 : if (GNUNET_OK !=
107 15 : GNUNET_PQ_extract_result (result,
108 : rs,
109 : i))
110 : {
111 0 : GNUNET_break (0);
112 0 : ltdo->qs = GNUNET_DB_STATUS_HARD_ERROR;
113 0 : return;
114 : }
115 15 : if (0 == i)
116 : {
117 15 : last_wtid = wtid;
118 15 : last_exchange_url = exchange_url;
119 15 : last_execution_time = execution_time;
120 15 : last_deposit_value = deposit_value;
121 15 : last_deposit_fee = deposit_fee;
122 15 : last_confirmed = confirmed;
123 15 : last_expected_credit_serial = expected_credit_serial;
124 15 : continue;
125 : }
126 0 : if ( (0 ==
127 0 : GNUNET_memcmp (&wtid,
128 0 : &last_wtid)) &&
129 0 : (0 == strcmp (exchange_url,
130 0 : last_exchange_url)) &&
131 0 : (expected_credit_serial ==
132 0 : last_expected_credit_serial) &&
133 0 : (GNUNET_TIME_timestamp_cmp (execution_time,
134 : ==,
135 0 : last_execution_time)) &&
136 0 : (last_confirmed == confirmed) &&
137 : (GNUNET_OK ==
138 0 : TALER_amount_cmp_currency (&deposit_value,
139 : &last_deposit_value)) )
140 : {
141 0 : GNUNET_assert (0 <=
142 : TALER_amount_add (&last_deposit_value,
143 : &last_deposit_value,
144 : &deposit_value));
145 0 : GNUNET_assert (0 <=
146 : TALER_amount_add (&last_deposit_fee,
147 : &last_deposit_fee,
148 : &deposit_fee));
149 0 : GNUNET_free (exchange_url);
150 0 : continue;
151 : }
152 0 : ltdo->cb (ltdo->cb_cls,
153 : &last_wtid,
154 : last_exchange_url,
155 : last_execution_time,
156 : &last_deposit_value,
157 : &last_deposit_fee,
158 : last_confirmed,
159 : last_expected_credit_serial);
160 0 : GNUNET_free (last_exchange_url);
161 0 : last_wtid = wtid;
162 0 : last_exchange_url = exchange_url;
163 0 : last_execution_time = execution_time;
164 0 : last_deposit_value = deposit_value;
165 0 : last_deposit_fee = deposit_fee;
166 0 : last_confirmed = confirmed;
167 0 : last_expected_credit_serial = expected_credit_serial;
168 : }
169 45 : if (num_results > 0)
170 : {
171 15 : ltdo->cb (ltdo->cb_cls,
172 : &last_wtid,
173 : last_exchange_url,
174 : last_execution_time,
175 : &last_deposit_value,
176 : &last_deposit_fee,
177 : last_confirmed,
178 : last_expected_credit_serial);
179 : }
180 45 : GNUNET_free (last_exchange_url);
181 45 : ltdo->qs = num_results;
182 : }
183 :
184 :
185 : enum GNUNET_DB_QueryStatus
186 45 : TALER_MERCHANTDB_iterate_transfer_details_by_order (
187 : struct TALER_MERCHANTDB_PostgresContext *pg,
188 : uint64_t order_serial,
189 : TALER_MERCHANTDB_OrderTransferDetailsCallback cb,
190 : void *cb_cls)
191 : {
192 45 : struct LookupTransferDetailsByOrderContext ltdo = {
193 : .pg = pg,
194 : .cb = cb,
195 : .cb_cls = cb_cls
196 : };
197 45 : struct GNUNET_PQ_QueryParam params[] = {
198 45 : GNUNET_PQ_query_param_uint64 (&order_serial),
199 : GNUNET_PQ_query_param_end
200 : };
201 : enum GNUNET_DB_QueryStatus qs;
202 :
203 45 : GNUNET_assert (NULL != pg->current_merchant_id);
204 45 : 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 45 : qs = GNUNET_PQ_eval_prepared_multi_select (
229 : pg->conn,
230 : "",
231 : params,
232 : &lookup_transfer_details_by_order_cb,
233 : <do);
234 45 : if (qs < 0)
235 0 : return qs;
236 45 : return ltdo.qs;
237 : }
|