gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant] 18/277: implement POST products/lock


From: gnunet
Subject: [taler-merchant] 18/277: implement POST products/lock
Date: Sun, 05 Jul 2020 20:48:51 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository merchant.

commit 458dc3653b4aef54130c580fd41610aa03f61d68
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Apr 19 22:22:46 2020 +0200

    implement POST products/lock
---
 src/backend/Makefile.am                            |   4 +-
 src/backend/taler-merchant-httpd.c                 |  11 +-
 ...aler-merchant-httpd_private-patch-products-ID.c |   2 +-
 ...aler-merchant-httpd_private-patch-products-ID.h |  14 +--
 ...-merchant-httpd_private-post-products-ID-lock.c | 126 +++++++++++++++++++++
 ...merchant-httpd_private-post-products-ID-lock.h} |  16 +--
 src/include/taler_merchantdb_plugin.h              |  30 ++++-
 7 files changed, 183 insertions(+), 20 deletions(-)

diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 646841d..58f11ed 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -40,7 +40,9 @@ taler_merchant_httpd_SOURCES = \
   taler-merchant-httpd_private-post-instances.c \
     taler-merchant-httpd_private-post-instances.h \
   taler-merchant-httpd_private-post-products.c \
-    taler-merchant-httpd_private-post-products.h
+    taler-merchant-httpd_private-post-products.h \
+  taler-merchant-httpd_private-post-products-ID-lock.c \
+    taler-merchant-httpd_private-post-products-ID-lock.h
 
 DEAD = \
   taler-merchant-httpd_check-payment.c taler-merchant-httpd_check-payment.h \
diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 58b6845..4efa6ad 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -37,6 +37,7 @@
 #include "taler-merchant-httpd_private-patch-instances-ID.h"
 #include "taler-merchant-httpd_private-patch-products-ID.h"
 #include "taler-merchant-httpd_private-post-instances.h"
+#include "taler-merchant-httpd_private-post-products-ID-lock.h"
 
 /**
  * Backlog for listen operation on unix-domain sockets.
@@ -785,11 +786,19 @@ url_handler (void *cls,
     },
     /* PATCH /products/$ID/: */
     {
-      .url_prefix = "/",
+      .url_prefix = "/products",
       .method = MHD_HTTP_METHOD_PATCH,
       .have_id_segment = true,
       .handler = &TMH_private_patch_products_ID
     },
+    /* POST /products/$ID/lock: */
+    {
+      .url_prefix = "/products",
+      .url_suffix = "lock",
+      .method = MHD_HTTP_METHOD_POST,
+      .have_id_segment = true,
+      .handler = &TMH_private_post_products_ID_lock
+    },
     {
       NULL
     }
diff --git a/src/backend/taler-merchant-httpd_private-patch-products-ID.c 
b/src/backend/taler-merchant-httpd_private-patch-products-ID.c
index 8177207..fd5a6c1 100644
--- a/src/backend/taler-merchant-httpd_private-patch-products-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-products-ID.c
@@ -169,7 +169,7 @@ TMH_private_patch_products_ID (const struct 
TMH_RequestHandler *rh,
       return TALER_MHD_reply_with_error (connection,
                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
                                          TALER_EC_INTERNAL_INVARIANT_FAILURE,
-                                         "Impossible to parse the order");
+                                         "Impossible to parse the product 
description");
   }
   if (-1 == total_stocked)
     pd.total_stocked = UINT64_MAX;
diff --git a/src/backend/taler-merchant-httpd_private-patch-products-ID.h 
b/src/backend/taler-merchant-httpd_private-patch-products-ID.h
index dde86a9..b034fd0 100644
--- a/src/backend/taler-merchant-httpd_private-patch-products-ID.h
+++ b/src/backend/taler-merchant-httpd_private-patch-products-ID.h
@@ -18,12 +18,12 @@
 */
 
 /**
- * @file backend/taler-merchant-httpd_private-patch-instances-ID.h
- * @brief implementing POST /instances request handling
+ * @file backend/taler-merchant-httpd_private-patch-products-ID.h
+ * @brief implementing POST /products request handling
  * @author Christian Grothoff
  */
-#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_INSTANCES_ID_H
-#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_INSTANCES_ID_H
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_PRODUCTS_ID_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_PRODUCTS_ID_H
 #include "taler-merchant-httpd.h"
 
 
@@ -36,8 +36,8 @@
  * @return MHD result code
  */
 MHD_RESULT
-TMH_private_patch_instances_ID (const struct TMH_RequestHandler *rh,
-                                struct MHD_Connection *connection,
-                                struct TMH_HandlerContext *hc);
+TMH_private_patch_products_ID (const struct TMH_RequestHandler *rh,
+                               struct MHD_Connection *connection,
+                               struct TMH_HandlerContext *hc);
 
 #endif
diff --git a/src/backend/taler-merchant-httpd_private-post-products-ID-lock.c 
b/src/backend/taler-merchant-httpd_private-post-products-ID-lock.c
new file mode 100644
index 0000000..bc35efd
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_private-post-products-ID-lock.c
@@ -0,0 +1,126 @@
+/*
+  This file is part of TALER
+  (C) 2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Affero General Public License as
+  published by the Free Software Foundation; either version 3,
+  or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not,
+  see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file backend/taler-merchant-httpd_private-post-products-ID-lock.c
+ * @brief implementing POST /products/$ID/lock request handling
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler-merchant-httpd_private-post-products-ID-lock.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Lock an existing product.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] hc context with further information about the request
+ * @return MHD result code
+ */
+MHD_RESULT
+TMH_private_post_products_ID_lock (const struct TMH_RequestHandler *rh,
+                                   struct MHD_Connection *connection,
+                                   struct TMH_HandlerContext *hc)
+{
+  struct TMH_MerchantInstance *mi = hc->instance;
+  const char *product_id = hc->infix;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_Uuid uuid;
+  uint32_t quantity;
+  struct GNUNET_TIME_Relative duration;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_fixed_auto ("lock_uuid",
+                                 &uuid),
+    GNUNET_JSON_spec_uint32 ("quantity",
+                             &quantity),
+    GNUNET_JSON_spec_relative_time ("duration",
+                                    &duration),
+    GNUNET_JSON_spec_end ()
+  };
+
+  GNUNET_assert (NULL != mi);
+  GNUNET_assert (NULL != product_id);
+  {
+    enum GNUNET_GenericReturnValue res;
+
+    res = TALER_MHD_parse_json_data (connection,
+                                     hc->request_body,
+                                     spec);
+    /* json is malformed */
+    if (GNUNET_NO == res)
+    {
+      GNUNET_break_op (0);
+      return MHD_YES;
+    }
+    /* other internal errors might have occurred */
+    if (GNUNET_SYSERR == res)
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         TALER_EC_INTERNAL_INVARIANT_FAILURE,
+                                         "Impossible to parse the lock 
request");
+  }
+
+  qs = TMH_db->lock_product (TMH_db->cls,
+                             mi->settings.id,
+                             product_id,
+                             &uuid,
+                             quantity,
+                             GNUNET_TIME_relative_to_absolute (duration));
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       
TALER_EC_PRODUCTS_PATCH_DB_COMMIT_HARD_ERROR,
+                                       "Failed to execute DB transaction to 
lock product");
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       TALER_EC_INTERNAL_INVARIANT_FAILURE,
+                                       "Serialization error for 
single-statment request");
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    qs = TMH_db->lookup_product (TMH_db->cls,
+                                 mi->settings.id,
+                                 product_id,
+                                 NULL);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_NOT_FOUND,
+                                         
TALER_EC_PRODUCTS_LOCK_UNKNOWN_PRODUCT,
+                                         "The specified product is unknown");
+    else
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_CONFLICT,
+                                         
TALER_EC_PRODUCTS_LOCK_INSUFFICIENT_STOCKS,
+                                         "The specified product is out of 
stock");
+  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    return TALER_MHD_reply_static (connection,
+                                   MHD_HTTP_NO_CONTENT,
+                                   NULL,
+                                   NULL,
+                                   0);
+  }
+  GNUNET_assert (0);
+  return MHD_NO;
+}
+
+
+/* end of taler-merchant-httpd_private-patch-products-ID-lock.c */
diff --git a/src/backend/taler-merchant-httpd_private-patch-products-ID.h 
b/src/backend/taler-merchant-httpd_private-post-products-ID-lock.h
similarity index 65%
copy from src/backend/taler-merchant-httpd_private-patch-products-ID.h
copy to src/backend/taler-merchant-httpd_private-post-products-ID-lock.h
index dde86a9..0d5d9a3 100644
--- a/src/backend/taler-merchant-httpd_private-patch-products-ID.h
+++ b/src/backend/taler-merchant-httpd_private-post-products-ID-lock.h
@@ -18,17 +18,17 @@
 */
 
 /**
- * @file backend/taler-merchant-httpd_private-patch-instances-ID.h
- * @brief implementing POST /instances request handling
+ * @file backend/taler-merchant-httpd_private-post-products-ID-lock.h
+ * @brief implementing POST /products/$ID/lock request handling
  * @author Christian Grothoff
  */
-#ifndef TALER_MERCHANT_HTTPD_PRIVATE_PATCH_INSTANCES_ID_H
-#define TALER_MERCHANT_HTTPD_PRIVATE_PATCH_INSTANCES_ID_H
+#ifndef TALER_MERCHANT_HTTPD_PRIVATE_POST_PRODUCTS_ID_LOCK_H
+#define TALER_MERCHANT_HTTPD_PRIVATE_POST_PRODUCTS_ID_LOCK_H
 #include "taler-merchant-httpd.h"
 
 
 /**
- * PATCH configuration of an existing instance, given its configuration.
+ * Lock an existing product.
  *
  * @param rh context of the handler
  * @param connection the MHD connection to handle
@@ -36,8 +36,8 @@
  * @return MHD result code
  */
 MHD_RESULT
-TMH_private_patch_instances_ID (const struct TMH_RequestHandler *rh,
-                                struct MHD_Connection *connection,
-                                struct TMH_HandlerContext *hc);
+TMH_private_post_products_ID_lock (const struct TMH_RequestHandler *rh,
+                                   struct MHD_Connection *connection,
+                                   struct TMH_HandlerContext *hc);
 
 #endif
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 28913f5..353997d 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -571,14 +571,19 @@ struct TALER_MERCHANTDB_Plugin
                     const struct TALER_MERCHANTDB_ProductDetails *pd);
 
   /**
-   * Update details about a particular product.
+   * Update details about a particular product. Note that the
+   * transaction must enforce that the sold/stocked/lost counters
+   * are not reduced (i.e. by expanding the WHERE clause on the existing
+   * values).
    *
    * @param cls closure
    * @param instance_id instance to lookup products for
    * @param product_id product to lookup
    * @param[out] pd set to the product details on success, can be NULL
    *             (in that case we only want to check if the product exists)
-   * @return database result code
+   * @return database result code, #GNUNET_DB_SUCCESS_NO_RESULTS if the
+   *         non-decreasing constraints are not met *or* if the product
+   *         does not yet exist.
    */
   enum GNUNET_DB_QueryStatus
   (*update_product)(void *cls,
@@ -586,6 +591,27 @@ struct TALER_MERCHANTDB_Plugin
                     const char *product_id,
                     struct TALER_MERCHANTDB_ProductDetails *pd);
 
+  /**
+   * Lock stocks of a particular product. Note that the transaction must
+   * enforce that the "stocked-sold-lost >= locked" constraint holds.
+   *
+   * @param cls closure
+   * @param instance_id instance to lookup products for
+   * @param product_id product to lookup
+   * @param uuid the UUID that holds the lock
+   * @param quantity how many units should be locked
+   * @param expiration_time when should the lock expire
+   * @return database result code, #GNUNET_DB_SUCCESS_NO_RESULTS if the
+   *         product is unknown OR if there insufficient stocks remaining
+   */
+  enum GNUNET_DB_QueryStatus
+  (*lock_product)(void *cls,
+                  const char *instance_id,
+                  const char *product_id,
+                  const struct GNUNET_Uuid *uuid,
+                  uint32_t quantity,
+                  struct GNUNET_TIME_Absolute expiration_time);
+
 
   /* ****************** OLD API ******************** */
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]