merchant

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

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


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