Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2022, 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 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/get_product.c
18 : * @brief Implementation of the get_product function for Postgres
19 : * @author Iván Ávalos
20 : */
21 : #include "platform.h"
22 : #include <taler/taler_pq_lib.h>
23 : #include "merchant-database/get_product.h"
24 : #include "helper.h"
25 :
26 :
27 : enum GNUNET_DB_QueryStatus
28 115 : TALER_MERCHANTDB_get_product (
29 : struct TALER_MERCHANTDB_PostgresContext *pg,
30 : const char *instance_id,
31 : const char *product_id,
32 : struct TALER_MERCHANTDB_ProductDetails *pd,
33 : size_t *num_categories,
34 : uint64_t **categories)
35 : {
36 115 : struct GNUNET_PQ_QueryParam params[] = {
37 115 : GNUNET_PQ_query_param_string (product_id),
38 : GNUNET_PQ_query_param_end
39 : };
40 :
41 115 : GNUNET_assert (NULL != pg->current_merchant_id);
42 115 : GNUNET_assert (0 == strcmp (instance_id,
43 : pg->current_merchant_id));
44 115 : TMH_PQ_prepare_anon (pg,
45 : "SELECT"
46 : " mi.description"
47 : ",mi.description_i18n::TEXT"
48 : ",mi.product_name"
49 : ",mi.unit"
50 : ",mi.price_array"
51 : ",mi.taxes::TEXT"
52 : ",mi.total_stock"
53 : ",mi.total_stock_frac"
54 : ",mi.allow_fractional_quantity"
55 : ",mi.fractional_precision_level"
56 : ",mi.total_sold"
57 : ",mi.total_sold_frac"
58 : ",mi.total_lost"
59 : ",mi.total_lost_frac"
60 : ",mi.total_locked"
61 : ",mi.total_locked_frac"
62 : ",mi.image"
63 : ",mi.address::TEXT"
64 : ",mi.next_restock"
65 : ",mi.minimum_age"
66 : ",mi.product_group_serial"
67 : ",mi.money_pot_serial"
68 : ",mi.price_is_net"
69 : ",t.category_array AS categories"
70 : " FROM merchant_inventory mi"
71 : ",LATERAL ("
72 : " SELECT ARRAY ("
73 : " SELECT mpc.category_serial"
74 : " FROM merchant_product_categories mpc"
75 : " WHERE mpc.product_serial = mi.product_serial"
76 : " ) AS category_array"
77 : " ) t"
78 : " WHERE mi.product_id=$1"
79 : );
80 115 : if (NULL == pd) // FIXME: is this case needed? For now yes: delete-private-products-PRODUCT_ID uses it!
81 : {
82 1 : struct GNUNET_PQ_ResultSpec rs_null[] = {
83 : GNUNET_PQ_result_spec_end
84 : };
85 :
86 1 : return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
87 : "",
88 : params,
89 : rs_null);
90 : }
91 : else
92 : {
93 114 : char *my_name = NULL;
94 114 : char *my_description = NULL;
95 114 : json_t *my_description_i18n = NULL;
96 114 : char *my_unit = NULL;
97 114 : char *my_image = NULL;
98 114 : json_t *my_address = NULL;
99 114 : json_t *my_taxes = NULL;
100 114 : uint64_t *my_categories = NULL;
101 114 : struct TALER_Amount *my_price_array = NULL;
102 114 : size_t my_price_array_length = 0;
103 114 : struct GNUNET_PQ_ResultSpec rs[] = {
104 114 : GNUNET_PQ_result_spec_string ("description",
105 : &my_description),
106 114 : TALER_PQ_result_spec_json ("description_i18n",
107 : &my_description_i18n),
108 114 : GNUNET_PQ_result_spec_string ("product_name",
109 : &my_name),
110 114 : GNUNET_PQ_result_spec_string ("unit",
111 : &my_unit),
112 114 : TALER_PQ_result_spec_array_amount_with_currency (pg->conn,
113 : "merchant",
114 : "price_array",
115 : &my_price_array_length,
116 : &my_price_array),
117 114 : TALER_PQ_result_spec_json ("taxes",
118 : &my_taxes),
119 114 : GNUNET_PQ_result_spec_uint64 ("total_stock",
120 : &pd->total_stock),
121 114 : GNUNET_PQ_result_spec_uint32 ("total_stock_frac",
122 : &pd->total_stock_frac),
123 114 : GNUNET_PQ_result_spec_bool ("allow_fractional_quantity",
124 : &pd->allow_fractional_quantity),
125 114 : GNUNET_PQ_result_spec_uint32 ("fractional_precision_level",
126 : &pd->fractional_precision_level),
127 114 : GNUNET_PQ_result_spec_uint64 ("total_sold",
128 : &pd->total_sold),
129 114 : GNUNET_PQ_result_spec_uint32 ("total_sold_frac",
130 : &pd->total_sold_frac),
131 114 : GNUNET_PQ_result_spec_uint64 ("total_lost",
132 : &pd->total_lost),
133 114 : GNUNET_PQ_result_spec_uint32 ("total_lost_frac",
134 : &pd->total_lost_frac),
135 114 : GNUNET_PQ_result_spec_uint64 ("total_locked",
136 : &pd->total_locked),
137 114 : GNUNET_PQ_result_spec_uint32 ("total_locked_frac",
138 : &pd->total_locked_frac),
139 114 : GNUNET_PQ_result_spec_string ("image",
140 : &my_image),
141 114 : TALER_PQ_result_spec_json ("address",
142 : &my_address),
143 114 : GNUNET_PQ_result_spec_timestamp ("next_restock",
144 : &pd->next_restock),
145 114 : GNUNET_PQ_result_spec_uint32 ("minimum_age",
146 : &pd->minimum_age),
147 114 : GNUNET_PQ_result_spec_array_uint64 (pg->conn,
148 : "categories",
149 : num_categories,
150 : &my_categories),
151 114 : GNUNET_PQ_result_spec_allow_null (
152 : GNUNET_PQ_result_spec_uint64 ("product_group_serial",
153 : &pd->product_group_id),
154 : NULL),
155 114 : GNUNET_PQ_result_spec_allow_null (
156 : GNUNET_PQ_result_spec_uint64 ("money_pot_serial",
157 : &pd->money_pot_id),
158 : NULL),
159 114 : GNUNET_PQ_result_spec_bool ("price_is_net",
160 : &pd->price_is_net),
161 : GNUNET_PQ_result_spec_end
162 : };
163 : enum GNUNET_DB_QueryStatus qs;
164 :
165 114 : pd->product_group_id = 0;
166 114 : pd->money_pot_id = 0;
167 114 : qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
168 : "",
169 : params,
170 : rs);
171 114 : pd->product_name = my_name;
172 114 : pd->description = my_description;
173 114 : pd->description_i18n = my_description_i18n;
174 114 : pd->unit = my_unit;
175 114 : pd->taxes = my_taxes;
176 114 : pd->image = my_image;
177 114 : pd->image_hash = NULL;
178 114 : pd->address = my_address;
179 114 : pd->price_array = my_price_array;
180 114 : pd->price_array_length = my_price_array_length;
181 114 : *categories = my_categories;
182 : /* Clear original pointers to that cleanup_result doesn't squash them */
183 114 : my_name = NULL;
184 114 : my_description = NULL;
185 114 : my_description_i18n = NULL;
186 114 : my_unit = NULL;
187 114 : my_taxes = NULL;
188 114 : my_image = NULL;
189 114 : my_address = NULL;
190 114 : my_price_array = NULL;
191 114 : my_price_array_length = 0;
192 114 : my_categories = NULL;
193 114 : GNUNET_PQ_cleanup_result (rs);
194 114 : return qs;
195 : }
196 : }
|