Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023 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 backenddb/pg_lookup_refunds_detailed.c
18 : * @brief Implementation of the lookup_refunds_detailed 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 "pg_lookup_refunds_detailed.h"
26 : #include "pg_helper.h"
27 :
28 : /**
29 : * Closure for #lookup_refunds_detailed_cb().
30 : */
31 : struct LookupRefundsDetailedContext
32 : {
33 : /**
34 : * Function to call for each refund.
35 : */
36 : TALER_MERCHANTDB_RefundDetailCallback rc;
37 :
38 : /**
39 : * Closure for @e rc.
40 : */
41 : void *rc_cls;
42 :
43 : /**
44 : * Plugin context.
45 : */
46 : struct PostgresClosure *pg;
47 :
48 : /**
49 : * Transaction result.
50 : */
51 : enum GNUNET_DB_QueryStatus qs;
52 : };
53 :
54 :
55 : /**
56 : * Function to be called with the results of a SELECT statement
57 : * that has returned @a num_results results.
58 : *
59 : * @param cls of type `struct GetRefundsContext *`
60 : * @param result the postgres result
61 : * @param num_results the number of results in @a result
62 : */
63 : static void
64 58 : lookup_refunds_detailed_cb (void *cls,
65 : PGresult *result,
66 : unsigned int num_results)
67 : {
68 58 : struct LookupRefundsDetailedContext *lrdc = cls;
69 :
70 94 : for (unsigned int i = 0; i<num_results; i++)
71 : {
72 : uint64_t refund_serial;
73 : struct GNUNET_TIME_Timestamp timestamp;
74 : struct TALER_CoinSpendPublicKeyP coin_pub;
75 : uint64_t rtransaction_id;
76 : struct TALER_Amount refund_amount;
77 : char *reason;
78 : char *exchange_url;
79 : uint8_t pending8;
80 36 : struct GNUNET_PQ_ResultSpec rs[] = {
81 36 : GNUNET_PQ_result_spec_uint64 ("refund_serial",
82 : &refund_serial),
83 36 : GNUNET_PQ_result_spec_timestamp ("refund_timestamp",
84 : ×tamp),
85 36 : GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
86 : &coin_pub),
87 36 : GNUNET_PQ_result_spec_string ("exchange_url",
88 : &exchange_url),
89 36 : GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
90 : &rtransaction_id),
91 36 : GNUNET_PQ_result_spec_string ("reason",
92 : &reason),
93 36 : TALER_PQ_result_spec_amount_with_currency ("refund_amount",
94 : &refund_amount),
95 36 : GNUNET_PQ_result_spec_auto_from_type ("pending",
96 : &pending8),
97 : GNUNET_PQ_result_spec_end
98 : };
99 :
100 36 : if (GNUNET_OK !=
101 36 : GNUNET_PQ_extract_result (result,
102 : rs,
103 : i))
104 : {
105 0 : GNUNET_break (0);
106 0 : lrdc->qs = GNUNET_DB_STATUS_HARD_ERROR;
107 0 : return;
108 : }
109 36 : lrdc->rc (lrdc->rc_cls,
110 : refund_serial,
111 : timestamp,
112 : &coin_pub,
113 : exchange_url,
114 : rtransaction_id,
115 : reason,
116 : &refund_amount,
117 : 0 != pending8);
118 36 : GNUNET_PQ_cleanup_result (rs);
119 : }
120 58 : lrdc->qs = num_results;
121 : }
122 :
123 :
124 : enum GNUNET_DB_QueryStatus
125 58 : TMH_PG_lookup_refunds_detailed (void *cls,
126 : const char *instance_id,
127 : const struct TALER_PrivateContractHashP *h_contract_terms,
128 : TALER_MERCHANTDB_RefundDetailCallback rc,
129 : void *rc_cls)
130 : {
131 58 : struct PostgresClosure *pg = cls;
132 58 : struct GNUNET_PQ_QueryParam params[] = {
133 58 : GNUNET_PQ_query_param_string (instance_id),
134 58 : GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
135 : GNUNET_PQ_query_param_end
136 : };
137 58 : struct LookupRefundsDetailedContext lrdc = {
138 : .rc = rc,
139 : .rc_cls = rc_cls,
140 : .pg = pg
141 : };
142 : enum GNUNET_DB_QueryStatus qs;
143 :
144 : /* no preflight check here, run in transaction by caller! */
145 58 : TALER_LOG_DEBUG ("Looking for refund %s + %s\n",
146 : GNUNET_h2s (&h_contract_terms->hash),
147 : instance_id);
148 :
149 58 : check_connection (pg);
150 58 : PREPARE (pg,
151 : "lookup_refunds_detailed",
152 : "SELECT"
153 : " ref.refund_serial"
154 : ",ref.refund_timestamp"
155 : ",dep.coin_pub"
156 : ",mcon.exchange_url"
157 : ",ref.rtransaction_id"
158 : ",ref.reason"
159 : ",ref.refund_amount"
160 : ",merchant_refund_proofs.exchange_sig IS NULL AS pending"
161 : " FROM merchant_deposit_confirmations mcon"
162 : " JOIN merchant_deposits dep"
163 : " USING (deposit_confirmation_serial)"
164 : " JOIN merchant_refunds ref"
165 : " USING (order_serial, coin_pub)"
166 : " LEFT JOIN merchant_refund_proofs"
167 : " USING (refund_serial)"
168 : " WHERE mcon.order_serial="
169 : " (SELECT order_serial"
170 : " FROM merchant_contract_terms"
171 : " WHERE h_contract_terms=$2"
172 : " AND merchant_serial="
173 : " (SELECT merchant_serial"
174 : " FROM merchant_instances"
175 : " WHERE merchant_id=$1))");
176 :
177 58 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
178 : "lookup_refunds_detailed",
179 : params,
180 : &lookup_refunds_detailed_cb,
181 : &lrdc);
182 58 : if (0 >= qs)
183 36 : return qs;
184 22 : return lrdc.qs;
185 : }
|