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