merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_get-private-pos.c (7809B)


      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/lookup_all_products.h"
     26 #include "merchant-database/lookup_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 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   struct Context *ctx = cls;
     64 
     65   (void) product_count;
     66   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 }
     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 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   struct Context *ctx = cls;
    100   json_t *pa = ctx->pa;
    101   json_t *cata;
    102   int64_t total_stock_api;
    103   char unit_total_stock_buf[64];
    104 
    105   cata = json_array ();
    106   GNUNET_assert (NULL != cata);
    107   for (size_t i = 0; i<num_categories; i++)
    108     GNUNET_assert (
    109       0 == json_array_append_new (
    110         cata,
    111         json_integer (categories[i])));
    112   if (0 == num_categories)
    113   {
    114     // If there is no category, we return the default category
    115     GNUNET_assert (
    116       0 == json_array_append_new (
    117         cata,
    118         json_integer (0)));
    119   }
    120   if (INT64_MAX == pd->total_stock)
    121     total_stock_api = -1;
    122   else
    123     total_stock_api = (int64_t) pd->total_stock;
    124   TALER_MERCHANT_vk_format_fractional_string (
    125     TALER_MERCHANT_VK_STOCK,
    126     pd->total_stock,
    127     pd->total_stock_frac,
    128     sizeof (unit_total_stock_buf),
    129     unit_total_stock_buf);
    130 
    131   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 }
    176 
    177 
    178 enum MHD_Result
    179 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   ctx.pa = json_array ();
    187   GNUNET_assert (NULL != ctx.pa);
    188   ctx.ca = json_array ();
    189   GNUNET_assert (NULL != ctx.ca);
    190   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   qs = TALER_MERCHANTDB_lookup_categories (TMH_db,
    199                                            hc->instance->settings.id,
    200                                            &add_category,
    201                                            &ctx);
    202   if (0 > qs)
    203   {
    204     GNUNET_break (0);
    205     json_decref (ctx.pa);
    206     json_decref (ctx.ca);
    207     return TALER_MHD_reply_with_error (connection,
    208                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    209                                        TALER_EC_GENERIC_DB_FETCH_FAILED,
    210                                        NULL);
    211   }
    212   qs = TALER_MERCHANTDB_lookup_all_products (TMH_db,
    213                                              hc->instance->settings.id,
    214                                              &add_product,
    215                                              &ctx);
    216   if (0 > qs)
    217   {
    218     GNUNET_break (0);
    219     json_decref (ctx.pa);
    220     json_decref (ctx.ca);
    221     return TALER_MHD_reply_with_error (connection,
    222                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    223                                        TALER_EC_GENERIC_DB_FETCH_FAILED,
    224                                        NULL);
    225   }
    226   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 */