Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2019, 2020, 2021, 2024 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-pos.c
18 : * @brief implement GET /private/pos
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include "taler-merchant-httpd_get-private-pos.h"
23 : #include <taler/taler_json_lib.h>
24 : #include "taler-merchant-httpd_helper.h"
25 : #include "merchant-database/iterate_all_products.h"
26 : #include "merchant-database/iterate_categories.h"
27 :
28 : /**
29 : * Closure for add_product().
30 : */
31 : struct Context
32 : {
33 : /**
34 : * JSON array of products we are building.
35 : */
36 : json_t *pa;
37 :
38 : /**
39 : * JSON array of categories we are building.
40 : */
41 : json_t *ca;
42 :
43 : };
44 :
45 :
46 : /**
47 : * Add category to the @e ca array.
48 : *
49 : * @param cls a `struct Context` with JSON arrays to build
50 : * @param category_id ID of the category
51 : * @param category_name name of the category
52 : * @param category_name_i18n translations of the @a category_name
53 : * @param product_count number of products in the category
54 : */
55 : static void
56 0 : add_category (
57 : void *cls,
58 : uint64_t category_id,
59 : const char *category_name,
60 : const json_t *category_name_i18n,
61 : uint64_t product_count)
62 : {
63 0 : struct Context *ctx = cls;
64 :
65 : (void) product_count;
66 0 : GNUNET_assert (
67 : 0 ==
68 : json_array_append_new (
69 : ctx->ca,
70 : GNUNET_JSON_PACK (
71 : GNUNET_JSON_pack_uint64 ("id",
72 : category_id),
73 : GNUNET_JSON_pack_object_incref ("name_i18n",
74 : (json_t *) category_name_i18n),
75 : GNUNET_JSON_pack_string ("name",
76 : category_name))));
77 0 : }
78 :
79 :
80 : /**
81 : * Add product details to our JSON array.
82 : *
83 : * @param cls a `struct Context` with JSON arrays to build
84 : * @param product_serial row ID of the product
85 : * @param product_id ID of the product
86 : * @param pd full product details
87 : * @param num_categories length of @a categories array
88 : * @param categories array of categories the
89 : * product is in
90 : */
91 : static void
92 0 : add_product (void *cls,
93 : uint64_t product_serial,
94 : const char *product_id,
95 : const struct TALER_MERCHANTDB_ProductDetails *pd,
96 : size_t num_categories,
97 : const uint64_t *categories)
98 : {
99 0 : struct Context *ctx = cls;
100 0 : json_t *pa = ctx->pa;
101 : json_t *cata;
102 : int64_t total_stock_api;
103 : char unit_total_stock_buf[64];
104 :
105 0 : cata = json_array ();
106 0 : GNUNET_assert (NULL != cata);
107 0 : for (size_t i = 0; i<num_categories; i++)
108 0 : GNUNET_assert (
109 : 0 == json_array_append_new (
110 : cata,
111 : json_integer (categories[i])));
112 0 : if (0 == num_categories)
113 : {
114 : // If there is no category, we return the default category
115 0 : GNUNET_assert (
116 : 0 == json_array_append_new (
117 : cata,
118 : json_integer (0)));
119 : }
120 0 : if (INT64_MAX == pd->total_stock)
121 0 : total_stock_api = -1;
122 : else
123 0 : total_stock_api = (int64_t) pd->total_stock;
124 0 : TALER_MERCHANT_vk_format_fractional_string (
125 : TALER_MERCHANT_VK_STOCK,
126 0 : pd->total_stock,
127 0 : pd->total_stock_frac,
128 : sizeof (unit_total_stock_buf),
129 : unit_total_stock_buf);
130 :
131 0 : GNUNET_assert (
132 : 0 ==
133 : json_array_append_new (
134 : pa,
135 : GNUNET_JSON_PACK (
136 : GNUNET_JSON_pack_string ("product_name",
137 : pd->product_name),
138 : GNUNET_JSON_pack_string ("description",
139 : pd->description),
140 : GNUNET_JSON_pack_object_incref ("description_i18n",
141 : (json_t *) pd->description_i18n),
142 : GNUNET_JSON_pack_string ("unit",
143 : pd->unit),
144 : // Note: deprecated field
145 : GNUNET_JSON_pack_allow_null (
146 : TALER_JSON_pack_amount ("price",
147 : (0 == pd->price_array_length)
148 : ? NULL
149 : : &pd->price_array[0])),
150 : TALER_JSON_pack_amount_array ("unit_price",
151 : pd->price_array_length,
152 : pd->price_array),
153 : GNUNET_JSON_pack_allow_null (
154 : GNUNET_JSON_pack_string ("image",
155 : pd->image)),
156 : GNUNET_JSON_pack_array_steal ("categories",
157 : cata),
158 : GNUNET_JSON_pack_allow_null (
159 : GNUNET_JSON_pack_array_incref ("taxes",
160 : (json_t *) pd->taxes)),
161 : GNUNET_JSON_pack_int64 ("total_stock",
162 : total_stock_api),
163 : GNUNET_JSON_pack_string ("unit_total_stock",
164 : unit_total_stock_buf),
165 : GNUNET_JSON_pack_bool ("unit_allow_fraction",
166 : pd->allow_fractional_quantity),
167 : GNUNET_JSON_pack_uint64 ("unit_precision_level",
168 : pd->fractional_precision_level),
169 : GNUNET_JSON_pack_uint64 ("minimum_age",
170 : pd->minimum_age),
171 : GNUNET_JSON_pack_uint64 ("product_serial",
172 : product_serial),
173 : GNUNET_JSON_pack_string ("product_id",
174 : product_id))));
175 0 : }
176 :
177 :
178 : enum MHD_Result
179 0 : TMH_private_get_pos (const struct TMH_RequestHandler *rh,
180 : struct MHD_Connection *connection,
181 : struct TMH_HandlerContext *hc)
182 : {
183 : struct Context ctx;
184 : enum GNUNET_DB_QueryStatus qs;
185 :
186 0 : ctx.pa = json_array ();
187 0 : GNUNET_assert (NULL != ctx.pa);
188 0 : ctx.ca = json_array ();
189 0 : GNUNET_assert (NULL != ctx.ca);
190 0 : GNUNET_assert (
191 : 0 == json_array_append_new (
192 : ctx.ca,
193 : GNUNET_JSON_PACK (
194 : GNUNET_JSON_pack_uint64 ("id",
195 : 0),
196 : GNUNET_JSON_pack_string ("name",
197 : "default"))));
198 0 : qs = TALER_MERCHANTDB_iterate_categories (TMH_db,
199 0 : hc->instance->settings.id,
200 : &add_category,
201 : &ctx);
202 0 : if (0 > qs)
203 : {
204 0 : GNUNET_break (0);
205 0 : json_decref (ctx.pa);
206 0 : json_decref (ctx.ca);
207 0 : return TALER_MHD_reply_with_error (connection,
208 : MHD_HTTP_INTERNAL_SERVER_ERROR,
209 : TALER_EC_GENERIC_DB_FETCH_FAILED,
210 : NULL);
211 : }
212 0 : qs = TALER_MERCHANTDB_iterate_all_products (TMH_db,
213 0 : hc->instance->settings.id,
214 : &add_product,
215 : &ctx);
216 0 : if (0 > qs)
217 : {
218 0 : GNUNET_break (0);
219 0 : json_decref (ctx.pa);
220 0 : json_decref (ctx.ca);
221 0 : return TALER_MHD_reply_with_error (connection,
222 : MHD_HTTP_INTERNAL_SERVER_ERROR,
223 : TALER_EC_GENERIC_DB_FETCH_FAILED,
224 : NULL);
225 : }
226 0 : return TALER_MHD_REPLY_JSON_PACK (
227 : connection,
228 : MHD_HTTP_OK,
229 : GNUNET_JSON_pack_array_steal ("categories",
230 : ctx.ca),
231 : GNUNET_JSON_pack_array_steal ("products",
232 : ctx.pa));
233 : }
234 :
235 :
236 : /* end of taler-merchant-httpd_get-private-pos.c */
|