LCOV - code coverage report
Current view: top level - backend - taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.4 % 72 50
Test Date: 2026-09-04 23:42:01 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   (C) 2020, 2021 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify
       6              :   it under the terms of the GNU Affero General Public License as
       7              :   published by the Free Software Foundation; either version 3,
       8              :   or (at your option) any later version.
       9              : 
      10              :   TALER is distributed in the hope that it will be useful, but
      11              :   WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13              :   GNU General Public License for more details.
      14              : 
      15              :   You should have received a copy of the GNU General Public
      16              :   License along with TALER; see the file COPYING.  If not,
      17              :   see <http://www.gnu.org/licenses/>
      18              : */
      19              : 
      20              : /**
      21              :  * @file src/backend/taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.c
      22              :  * @brief implementing POST /products/$ID/lock request handling
      23              :  * @author Christian Grothoff
      24              :  */
      25              : #include "platform.h"
      26              : #include "taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.h"
      27              : #include "taler-merchant-httpd_helper.h"
      28              : #include <taler/taler_json_lib.h>
      29              : #include "merchant-database/do_expire_locks.h"
      30              : #include "merchant-database/insert_inventory_lock.h"
      31              : #include "merchant-database/get_product.h"
      32              : 
      33              : 
      34              : enum MHD_Result
      35           14 : TMH_private_post_products_ID_lock (
      36              :   const struct TMH_RequestHandler *rh,
      37              :   struct MHD_Connection *connection,
      38              :   struct TMH_HandlerContext *hc)
      39              : {
      40           14 :   struct TMH_MerchantInstance *mi = hc->instance;
      41           14 :   const char *product_id = hc->infix;
      42              :   enum GNUNET_DB_QueryStatus qs;
      43              :   const char *uuids;
      44              :   struct GNUNET_Uuid uuid;
      45              :   uint64_t quantity;
      46              :   bool quantity_missing;
      47           14 :   const char *unit_quantity = NULL;
      48           14 :   bool unit_quantity_missing = true;
      49              :   struct GNUNET_TIME_Relative duration;
      50              :   struct GNUNET_JSON_Specification spec[] = {
      51           14 :     GNUNET_JSON_spec_string ("lock_uuid",
      52              :                              &uuids),
      53           14 :     GNUNET_JSON_spec_relative_time ("duration",
      54              :                                     &duration),
      55           14 :     GNUNET_JSON_spec_mark_optional (
      56              :       GNUNET_JSON_spec_uint64 ("quantity",
      57              :                                &quantity),
      58              :       &quantity_missing),
      59           14 :     GNUNET_JSON_spec_mark_optional (
      60              :       GNUNET_JSON_spec_string ("unit_quantity",
      61              :                                &unit_quantity),
      62              :       &unit_quantity_missing),
      63           14 :     GNUNET_JSON_spec_end ()
      64              :   };
      65              : 
      66           14 :   GNUNET_assert (NULL != mi);
      67           14 :   GNUNET_assert (NULL != product_id);
      68              :   {
      69              :     enum GNUNET_GenericReturnValue res;
      70              : 
      71           14 :     res = TALER_MHD_parse_json_data (connection,
      72           14 :                                      hc->request_body,
      73              :                                      spec);
      74           14 :     if (GNUNET_OK != res)
      75              :       return (GNUNET_NO == res)
      76              :              ? MHD_YES
      77            0 :              : MHD_NO;
      78              :   }
      79           14 :   TMH_uuid_from_string (uuids,
      80              :                         &uuid);
      81           14 :   TALER_MERCHANTDB_do_expire_locks (TMH_db);
      82              :   {
      83           14 :     struct TALER_MERCHANTDB_ProductDetails pd = { 0 };
      84              :     size_t num_categories;
      85              :     uint64_t *categories;
      86           14 :     uint64_t normalized_quantity = 0;
      87           14 :     uint32_t normalized_quantity_frac = 0;
      88              : 
      89           14 :     if (quantity_missing && unit_quantity_missing)
      90              :     {
      91            0 :       quantity = 1;
      92            0 :       quantity_missing = false;
      93              :     }
      94           14 :     else if ( (! quantity_missing) &&
      95            0 :               (quantity > (uint64_t) INT64_MAX) )
      96              :     {
      97            0 :       GNUNET_break_op (0);
      98            4 :       return TALER_MHD_reply_with_error (connection,
      99              :                                          MHD_HTTP_BAD_REQUEST,
     100              :                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
     101              :                                          "quantity");
     102              :     }
     103              : 
     104           14 :     qs = TALER_MERCHANTDB_get_product (TMH_db,
     105           14 :                                        mi->settings.id,
     106              :                                        product_id,
     107              :                                        &pd,
     108              :                                        &num_categories,
     109              :                                        &categories);
     110           14 :     switch (qs)
     111              :     {
     112            0 :     case GNUNET_DB_STATUS_HARD_ERROR:
     113            0 :       GNUNET_break (0);
     114            0 :       TALER_MERCHANTDB_product_details_free (&pd);
     115            0 :       GNUNET_free (categories);
     116            0 :       return TALER_MHD_reply_with_error (
     117              :         connection,
     118              :         MHD_HTTP_INTERNAL_SERVER_ERROR,
     119              :         TALER_EC_GENERIC_DB_FETCH_FAILED,
     120              :         "get_product");
     121            0 :     case GNUNET_DB_STATUS_SOFT_ERROR:
     122            0 :       GNUNET_break (0);
     123            0 :       TALER_MERCHANTDB_product_details_free (&pd);
     124            0 :       GNUNET_free (categories);
     125            0 :       return TALER_MHD_reply_with_error (
     126              :         connection,
     127              :         MHD_HTTP_INTERNAL_SERVER_ERROR,
     128              :         TALER_EC_GENERIC_DB_SOFT_FAILURE,
     129              :         "get_product");
     130            2 :     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     131            2 :       GNUNET_break_op (0);
     132            2 :       TALER_MERCHANTDB_product_details_free (&pd);
     133            2 :       GNUNET_free (categories);
     134            2 :       return TALER_MHD_reply_with_error (
     135              :         connection,
     136              :         MHD_HTTP_NOT_FOUND,
     137              :         TALER_EC_MERCHANT_GENERIC_PRODUCT_UNKNOWN,
     138              :         product_id);
     139           12 :     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     140           12 :       break;
     141              :     }
     142           12 :     GNUNET_free (categories);
     143              :     {
     144              :       const char *eparam;
     145           12 :       if (GNUNET_OK !=
     146           12 :           TALER_MERCHANT_vk_process_quantity_inputs (
     147              :             TALER_MERCHANT_VK_QUANTITY,
     148           12 :             pd.allow_fractional_quantity,
     149              :             quantity_missing,
     150              :             (int64_t) quantity,
     151              :             unit_quantity_missing,
     152              :             unit_quantity,
     153              :             &normalized_quantity,
     154              :             &normalized_quantity_frac,
     155              :             &eparam))
     156              :       {
     157            2 :         TALER_MERCHANTDB_product_details_free (&pd);
     158            2 :         GNUNET_break_op (0);
     159            2 :         return TALER_MHD_reply_with_error (connection,
     160              :                                            MHD_HTTP_BAD_REQUEST,
     161              :                                            TALER_EC_GENERIC_PARAMETER_MALFORMED,
     162              :                                            eparam);
     163              :       }
     164              :     }
     165           10 :     quantity = normalized_quantity;
     166           10 :     qs = TALER_MERCHANTDB_insert_inventory_lock (TMH_db,
     167           10 :                                                  mi->settings.id,
     168              :                                                  product_id,
     169              :                                                  &uuid,
     170              :                                                  quantity,
     171              :                                                  normalized_quantity_frac,
     172              :                                                  GNUNET_TIME_relative_to_timestamp (duration));
     173           10 :     TALER_MERCHANTDB_product_details_free (&pd);
     174              :   }
     175           10 :   switch (qs)
     176              :   {
     177            0 :   case GNUNET_DB_STATUS_HARD_ERROR:
     178            0 :     GNUNET_break (0);
     179            0 :     return TALER_MHD_reply_with_error (
     180              :       connection,
     181              :       MHD_HTTP_INTERNAL_SERVER_ERROR,
     182              :       TALER_EC_GENERIC_DB_STORE_FAILED,
     183              :       NULL);
     184            0 :   case GNUNET_DB_STATUS_SOFT_ERROR:
     185            0 :     GNUNET_break (0);
     186            0 :     return TALER_MHD_reply_with_error (
     187              :       connection,
     188              :       MHD_HTTP_INTERNAL_SERVER_ERROR,
     189              :       TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
     190              :       "Serialization error for single-statment request");
     191            3 :   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     192            3 :     GNUNET_break_op (0);
     193            3 :     return TALER_MHD_reply_with_error (
     194              :       connection,
     195              :       MHD_HTTP_GONE,
     196              :       TALER_EC_MERCHANT_PRIVATE_POST_PRODUCTS_LOCK_INSUFFICIENT_STOCKS,
     197              :       product_id);
     198            7 :   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     199            7 :     return TALER_MHD_reply_static (connection,
     200              :                                    MHD_HTTP_NO_CONTENT,
     201              :                                    NULL,
     202              :                                    NULL,
     203              :                                    0);
     204              :   }
     205            0 :   GNUNET_assert (0);
     206              :   return MHD_NO;
     207              : }
     208              : 
     209              : 
     210              : /* end of taler-merchant-httpd_post-private-products-PRODUCT_ID-lock.c */
        

Generated by: LCOV version 2.0-1