Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2025 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU Affero 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/backend/taler-merchant-httpd_get-private-statistics-amount-SLUG.c
18 : * @brief implement GET /statistics-amount/$SLUG/
19 : * @author Martin Schanzenbach
20 : */
21 : #include "platform.h"
22 : #include "taler-merchant-httpd_get-private-statistics-amount-SLUG.h"
23 : #include <gnunet/gnunet_json_lib.h>
24 : #include <taler/taler_json_lib.h>
25 : #include "merchant-database/iterate_statistic_bucket_amounts.h"
26 : #include "merchant-database/iterate_statistic_interval_amounts.h"
27 :
28 :
29 : /**
30 : * Typically called by `iterate_statistic_bucket_amounts`.
31 : *
32 : * @param cls a `json_t *` JSON array to build
33 : * @param description description of the statistic
34 : * @param bucket_start start time of the bucket
35 : * @param bucket_end end time of the bucket
36 : * @param bucket_range range of the bucket
37 : * @param amounts_len the length of @a cumulative_amounts
38 : * @param amounts the cumulative amounts array
39 : */
40 : static void
41 12 : amount_by_bucket (void *cls,
42 : const char *description,
43 : struct GNUNET_TIME_Timestamp bucket_start,
44 : struct GNUNET_TIME_Timestamp bucket_end,
45 : const char *bucket_range,
46 : unsigned int amounts_len,
47 : const struct TALER_Amount amounts[static amounts_len])
48 12 : {
49 12 : json_t *root = cls;
50 : json_t *amount_array;
51 : json_t *buckets_array;
52 :
53 12 : GNUNET_assert (json_is_object (root));
54 12 : buckets_array = json_object_get (root,
55 : "buckets");
56 12 : GNUNET_assert (NULL != buckets_array);
57 12 : GNUNET_assert (json_is_array (buckets_array));
58 :
59 12 : amount_array = json_array ();
60 12 : GNUNET_assert (NULL != amount_array);
61 24 : for (unsigned int i = 0; i < amounts_len; i++)
62 : {
63 12 : GNUNET_assert (
64 : 0 ==
65 : json_array_append_new (amount_array,
66 : TALER_JSON_from_amount (&amounts[i])));
67 : }
68 :
69 12 : GNUNET_assert (
70 : 0 ==
71 : json_array_append_new (
72 : buckets_array,
73 : GNUNET_JSON_PACK (
74 : GNUNET_JSON_pack_timestamp (
75 : "start_time",
76 : bucket_start),
77 : GNUNET_JSON_pack_timestamp (
78 : "end_time",
79 : bucket_end),
80 : GNUNET_JSON_pack_string (
81 : "range",
82 : bucket_range),
83 : GNUNET_JSON_pack_array_steal (
84 : "cumulative_amounts",
85 : amount_array))));
86 12 : if (NULL == json_object_get (root,
87 : "buckets_description"))
88 : {
89 2 : GNUNET_assert (0 ==
90 : json_object_set_new (root,
91 : "buckets_description",
92 : json_string (description)));
93 : }
94 12 : }
95 :
96 :
97 : /**
98 : * Typically called by `iterate_statistic_interval_amounts`.
99 : *
100 : * @param cls a `json_t *` JSON array to build
101 : * @param description description of the statistic
102 : * @param bucket_start start time of the bucket
103 : * @param amounts_len the length of @a cumulative_amounts
104 : * @param amounts the cumulative amounts array
105 : */
106 : static void
107 0 : amount_by_interval (void *cls,
108 : const char *description,
109 : struct GNUNET_TIME_Timestamp bucket_start,
110 : unsigned int amounts_len,
111 : const struct TALER_Amount amounts[static amounts_len])
112 0 : {
113 : json_t *root;
114 : json_t *amount_array;
115 : json_t *intervals_array;
116 :
117 0 : root = cls;
118 0 : GNUNET_assert (json_is_object (root));
119 0 : intervals_array = json_object_get (root,
120 : "intervals");
121 0 : GNUNET_assert (NULL != intervals_array);
122 0 : GNUNET_assert (json_is_array (intervals_array));
123 :
124 0 : amount_array = json_array ();
125 0 : GNUNET_assert (NULL != amount_array);
126 0 : for (unsigned int i = 0; i < amounts_len; i++)
127 : {
128 0 : GNUNET_assert (
129 : 0 ==
130 : json_array_append_new (amount_array,
131 : TALER_JSON_from_amount (&amounts[i])));
132 : }
133 :
134 :
135 0 : GNUNET_assert (
136 : 0 ==
137 : json_array_append_new (
138 : intervals_array,
139 : GNUNET_JSON_PACK (
140 : GNUNET_JSON_pack_timestamp (
141 : "start_time",
142 : bucket_start),
143 : GNUNET_JSON_pack_array_steal (
144 : "cumulative_amounts",
145 : amount_array))));
146 0 : if (NULL == json_object_get (root,
147 : "intervals_description"))
148 : {
149 0 : GNUNET_assert (
150 : 0 ==
151 : json_object_set_new (root,
152 : "intervals_description",
153 : json_string (description)));
154 : }
155 0 : }
156 :
157 :
158 : /**
159 : * Handle a GET "/statistics-amount/$SLUG" request.
160 : *
161 : * @param rh context of the handler
162 : * @param connection the MHD connection to handle
163 : * @param[in,out] hc context with further information about the request
164 : * @return MHD result code
165 : */
166 : enum MHD_Result
167 2 : TMH_private_get_statistics_amount_SLUG (const struct TMH_RequestHandler *rh,
168 : struct MHD_Connection *connection,
169 : struct TMH_HandlerContext *hc)
170 : {
171 2 : struct TMH_MerchantInstance *mi = hc->instance;
172 : json_t *root;
173 2 : bool get_buckets = true;
174 2 : bool get_intervals = true;
175 :
176 2 : GNUNET_assert (NULL != mi);
177 : {
178 : const char *filter;
179 :
180 2 : filter = MHD_lookup_connection_value (connection,
181 : MHD_GET_ARGUMENT_KIND,
182 : "by");
183 2 : if (NULL != filter)
184 : {
185 0 : if (0 == strcasecmp (filter,
186 : "bucket"))
187 0 : get_intervals = false;
188 0 : else if (0 == strcasecmp (filter,
189 : "interval"))
190 0 : get_buckets = false;
191 0 : else if (0 != strcasecmp (filter,
192 : "any"))
193 : {
194 0 : GNUNET_break_op (0);
195 0 : return TALER_MHD_reply_with_error (
196 : connection,
197 : MHD_HTTP_BAD_REQUEST,
198 : TALER_EC_GENERIC_PARAMETER_MALFORMED,
199 : "by");
200 : }
201 : }
202 : }
203 2 : root = GNUNET_JSON_PACK (
204 : GNUNET_JSON_pack_array_steal ("intervals",
205 : json_array ()),
206 : GNUNET_JSON_pack_array_steal ("buckets",
207 : json_array ()));
208 2 : if (get_buckets)
209 : {
210 : enum GNUNET_DB_QueryStatus qs;
211 :
212 2 : qs = TALER_MERCHANTDB_iterate_statistic_bucket_amounts (
213 : TMH_db,
214 2 : mi->settings.id,
215 2 : hc->infix,
216 : &amount_by_bucket,
217 : root);
218 2 : if (0 > qs)
219 : {
220 0 : GNUNET_break (0);
221 0 : json_decref (root);
222 0 : return TALER_MHD_reply_with_error (
223 : connection,
224 : MHD_HTTP_INTERNAL_SERVER_ERROR,
225 : TALER_EC_GENERIC_DB_FETCH_FAILED,
226 : "iterate_statistic_bucket_amounts");
227 : }
228 : }
229 2 : if (get_intervals)
230 : {
231 : enum GNUNET_DB_QueryStatus qs;
232 :
233 2 : qs = TALER_MERCHANTDB_iterate_statistic_interval_amounts (
234 : TMH_db,
235 2 : mi->settings.id,
236 2 : hc->infix,
237 : &amount_by_interval,
238 : root);
239 2 : if (0 > qs)
240 : {
241 0 : GNUNET_break (0);
242 0 : json_decref (root);
243 0 : return TALER_MHD_reply_with_error (
244 : connection,
245 : MHD_HTTP_INTERNAL_SERVER_ERROR,
246 : TALER_EC_GENERIC_DB_FETCH_FAILED,
247 : "iterate_statistic_interval_amounts");
248 : }
249 : }
250 2 : return TALER_MHD_reply_json (connection,
251 : root,
252 : MHD_HTTP_OK);
253 : }
254 :
255 :
256 : /* end of taler-merchant-httpd_get-private-statistics-amount-SLUG.c */
|