merchant

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

taler-merchant-httpd_get-private-statistics-amount-SLUG.c (7782B)


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