[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant] 81/277: fix/complete inventory management logic
From: |
gnunet |
Subject: |
[taler-merchant] 81/277: fix/complete inventory management logic |
Date: |
Sun, 05 Jul 2020 20:49:54 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository merchant.
commit 9e90a4432b414382344ea525a34af27e661523f4
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat May 2 22:03:52 2020 +0200
fix/complete inventory management logic
---
src/backend/taler-merchant-httpd_exchanges.c | 143 ++++++++++++++-------
.../taler-merchant-httpd_post-orders-ID-abort.c | 4 +-
.../taler-merchant-httpd_post-orders-ID-claim.c | 11 --
src/backenddb/plugin_merchantdb_postgres.c | 57 +++++++-
src/include/taler_merchantdb_plugin.h | 4 +-
src/lib/merchant_api_post_order_abort.c | 24 +++-
6 files changed, 169 insertions(+), 74 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_exchanges.c
b/src/backend/taler-merchant-httpd_exchanges.c
index f874bb9..ef5bde9 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -22,6 +22,7 @@
#include "platform.h"
#include <taler/taler_json_lib.h>
#include "taler-merchant-httpd_exchanges.h"
+#include "taler-merchant-httpd.h"
/**
@@ -726,6 +727,70 @@ wire_task_cb (void *cls)
}
+/**
+ * We failed downloading /keys from @a exchange. Tell clients
+ * about our failure, abort pending operations and retry later.
+ *
+ * @param exchange exchange that failed
+ * @param hr details about the HTTP reply
+ * @param compat version compatibility data
+ */
+static void
+fail_and_retry (struct Exchange *exchange,
+ const struct TALER_EXCHANGE_HttpResponse *hr,
+ enum TALER_EXCHANGE_VersionCompatibility compat)
+{
+ struct TMH_EXCHANGES_FindOperation *fo;
+
+ exchange->pending = GNUNET_YES;
+ if (NULL != exchange->wire_request)
+ {
+ TALER_EXCHANGE_wire_cancel (exchange->wire_request);
+ exchange->wire_request = NULL;
+ }
+ if (NULL != exchange->wire_task)
+ {
+ GNUNET_SCHEDULER_cancel (exchange->wire_task);
+ exchange->wire_task = NULL;
+ }
+ while (NULL != (fo = exchange->fo_head))
+ {
+ fo->fc (fo->fc_cls,
+ hr,
+ NULL,
+ NULL,
+ GNUNET_NO);
+ TMH_EXCHANGES_find_exchange_cancel (fo);
+ }
+ if (TALER_EXCHANGE_VC_INCOMPATIBLE_NEWER == compat)
+ {
+ /* Log hard error: we likely need admin help! */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Exchange `%s' runs an incompatible more recent version of the
Taler protocol. Will not retry. This client may need to be updated.\n",
+ exchange->url);
+ /* Theoretically, the exchange could downgrade,
+ but let's not be too aggressive about retries
+ on this one. */
+ exchange->retry_delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_HOURS,
+ exchange->retry_delay);
+ }
+ exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to fetch /keys from `%s': %d/%u, retrying in %s\n",
+ exchange->url,
+ (int) hr->ec,
+ hr->http_status,
+ GNUNET_STRINGS_relative_time_to_string (exchange->retry_delay,
+ GNUNET_YES));
+ GNUNET_assert (NULL == exchange->retry_task);
+ exchange->first_retry = GNUNET_TIME_relative_to_absolute (
+ exchange->retry_delay);
+ exchange->retry_task = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay,
+ &retry_exchange,
+ exchange);
+}
+
+
/**
* Function called with information about who is auditing
* a particular exchange and what key the exchange is using.
@@ -754,54 +819,9 @@ keys_mgmt_cb (void *cls,
if (NULL == keys)
{
- struct TMH_EXCHANGES_FindOperation *fo;
-
- exchange->pending = GNUNET_YES;
- if (NULL != exchange->wire_request)
- {
- TALER_EXCHANGE_wire_cancel (exchange->wire_request);
- exchange->wire_request = NULL;
- }
- if (NULL != exchange->wire_task)
- {
- GNUNET_SCHEDULER_cancel (exchange->wire_task);
- exchange->wire_task = NULL;
- }
- while (NULL != (fo = exchange->fo_head))
- {
- fo->fc (fo->fc_cls,
- hr,
- NULL,
- NULL,
- GNUNET_NO);
- TMH_EXCHANGES_find_exchange_cancel (fo);
- }
- if (TALER_EXCHANGE_VC_INCOMPATIBLE_NEWER == compat)
- {
- /* Log hard error: we likely need admin help! */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Exchange `%s' runs an incompatible more recent version of
the Taler protocol. Will not retry. This client may need to be updated.\n",
- exchange->url);
- /* Theoretically, the exchange could downgrade,
- but let's not be too aggressive about retries
- on this one. */
- exchange->retry_delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_HOURS,
- exchange->retry_delay);
- }
- exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to fetch /keys from `%s': %d/%u, retrying in %s\n",
- exchange->url,
- (int) hr->ec,
- hr->http_status,
- GNUNET_STRINGS_relative_time_to_string (exchange->retry_delay,
- GNUNET_YES));
- GNUNET_assert (NULL == exchange->retry_task);
- exchange->first_retry = GNUNET_TIME_relative_to_absolute (
- exchange->retry_delay);
- exchange->retry_task = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay,
- &retry_exchange,
- exchange);
+ fail_and_retry (exchange,
+ hr,
+ compat);
return;
}
if ( (GNUNET_YES == exchange->trusted) &&
@@ -830,8 +850,31 @@ keys_mgmt_cb (void *cls,
exchange->url);
}
}
- // FIXME: go over keys->sign_keys and STORE
- // all of those into our database!
+
+ /* store exchange online signing keys in our DB */
+ for (unsigned int i = 0; i<keys->num_sign_keys; i++)
+ {
+ struct TALER_EXCHANGE_SigningPublicKey *sign_key = &keys->sign_keys[i];
+ enum GNUNET_DB_QueryStatus qs;
+
+ TMH_db->preflight (TMH_db->cls);
+ qs = TMH_db->insert_exchange_signkey (TMH_db->cls,
+ &keys->master_pub,
+ &sign_key->key,
+ sign_key->valid_from,
+ sign_key->valid_until,
+ sign_key->valid_legal,
+ &sign_key->master_sig);
+ /* 0 is OK, we may already have the key in the DB! */
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ fail_and_retry (exchange,
+ hr,
+ compat);
+ return;
+ }
+ }
expire = TALER_EXCHANGE_check_keys_current (exchange->conn,
GNUNET_NO,
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
index 08773a7..4c7960e 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
@@ -741,7 +741,7 @@ begin_transaction (struct AbortContext *ac)
/* Payment is complete, refuse to abort. */
TMH_db->rollback (TMH_db->cls);
resume_abort_with_error (ac,
- MHD_HTTP_FORBIDDEN,
+ MHD_HTTP_PRECONDITION_FAILED,
TALER_EC_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE,
"Payment was complete, refusing to abort");
return;
@@ -753,7 +753,7 @@ begin_transaction (struct AbortContext *ac)
{
GNUNET_break_op (0);
resume_abort_with_error (ac,
- MHD_HTTP_BAD_REQUEST,
+ MHD_HTTP_FORBIDDEN,
TALER_EC_ABORT_CONTRACT_HASH_MISSMATCH,
"Provided hash does not match order on file");
return;
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
b/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
index 17ef013..80c178b 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
@@ -103,17 +103,6 @@ claim_order (const char *instance_id,
*contract_terms = NULL;
return qs;
}
- qs = TMH_db->delete_order (TMH_db->cls,
- instance_id,
- order_id);
- if (0 >= qs)
- {
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- json_decref (*contract_terms);
- *contract_terms = NULL;
- return qs;
- }
qs = TMH_db->commit (TMH_db->cls);
if (0 > qs)
return qs;
diff --git a/src/backenddb/plugin_merchantdb_postgres.c
b/src/backenddb/plugin_merchantdb_postgres.c
index 8f1a864..784650a 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -1863,7 +1863,8 @@ postgres_lookup_refunds (void *cls,
/**
* Mark contract as paid and store the current @a session_id
- * for which the contract was paid.
+ * for which the contract was paid. Deletes the underlying order
+ * and marks the locked stocks of the order as sold.
*
* @param cls closure
* @param instance_id instance to mark contract as paid for
@@ -1884,6 +1885,12 @@ postgres_mark_contract_paid (void *cls,
GNUNET_PQ_query_param_string (session_id),
GNUNET_PQ_query_param_end
};
+ struct GNUNET_PQ_QueryParam uparams[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
/* no preflight check here, run in transaction by caller! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1891,9 +1898,19 @@ postgres_mark_contract_paid (void *cls,
GNUNET_h2s (h_contract_terms),
instance_id,
session_id);
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "mark_contract_paid",
+ params);
+ if (qs <= 0)
+ return qs;
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "mark_inventory_sold",
+ uparams);
+ if (qs < 0)
+ return qs; /* 0: no inventory management, that's OK! */
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "mark_contract_paid",
- params);
+ "delete_completed_order",
+ uparams);
}
@@ -5472,6 +5489,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" FULL OUTER JOIN ed ON TRUE"
" WHERE h_contract_terms=$2",
16),
+ /* for postgres_lookup_refunds() */
GNUNET_PQ_make_prepare ("lookup_refunds",
"SELECT"
" coin_pub"
@@ -5487,6 +5505,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" FROM merchant_instances"
" WHERE merchant_id=$1))",
2),
+ /* for postgres_mark_contract_paid() */
GNUNET_PQ_make_prepare ("mark_contract_paid",
"UPDATE merchant_contract_terms SET"
" paid=TRUE"
@@ -5497,6 +5516,38 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" FROM merchant_instances"
" WHERE merchant_id=$1)",
3),
+ /* for postgres_mark_contract_paid() */
+ GNUNET_PQ_make_prepare ("mark_inventory_sold",
+ "UPDATE merchant_inventory SET"
+ " total_sold=total_sold + order_locks.total_locked"
+ " FROM (SELECT total_locked,product_serial"
+ " FROM merchant_order_locks"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))"
+ " ) AS order_locks"
+ " WHERE merchant_inventory.product_serial"
+ " =order_locks.product_serial",
+ 2),
+ /* for postgres_mark_contract_paid() */
+ GNUNET_PQ_make_prepare ("delete_completed_order",
+ "WITH md AS"
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1) "
+ "DELETE"
+ " FROM merchant_orders"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " JOIN md USING (merchant_serial)"
+ " WHERE h_contract_terms=$2)",
+ 2),
/* for postgres_refund_coin() */
GNUNET_PQ_make_prepare ("refund_coin",
"INSERT INTO merchant_refunds"
diff --git a/src/include/taler_merchantdb_plugin.h
b/src/include/taler_merchantdb_plugin.h
index d2e7801..a58cb7d 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -779,6 +779,7 @@ struct TALER_MERCHANTDB_Plugin
const char *instance_id,
const char *order_id);
+
/**
* Retrieve order given its @a order_id and the @a instance_id.
*
@@ -1016,7 +1017,8 @@ struct TALER_MERCHANTDB_Plugin
/**
* Mark contract as paid and store the current @a session_id
- * for which the contract was paid.
+ * for which the contract was paid. Deletes the underlying order
+ * and marks the locked stocks of the order as sold.
*
* @param cls closure
* @param instance_id instance to mark contract as paid for
diff --git a/src/lib/merchant_api_post_order_abort.c
b/src/lib/merchant_api_post_order_abort.c
index 9b45e38..6ee20f9 100644
--- a/src/lib/merchant_api_post_order_abort.c
+++ b/src/lib/merchant_api_post_order_abort.c
@@ -122,8 +122,13 @@ check_abort_refund (struct TALER_MERCHANT_OrderAbortHandle
*ph,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+ if (! json_is_array (refunds))
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ return GNUNET_SYSERR;
+ }
num_refunds = json_array_size (refunds);
- // FIXME: test for array first!
{
struct TALER_MERCHANT_AbortedCoin res[GNUNET_NZL (num_refunds)];
@@ -380,11 +385,18 @@ handle_abort_finished (void *cls,
merchant is buggy (or API version conflict); just
pass JSON reply to the application */
break;
- case MHD_HTTP_CONFLICT:
+ case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
break;
- case MHD_HTTP_FORBIDDEN:
+ case MHD_HTTP_NOT_FOUND:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the
+ application */
+ break;
+ case MHD_HTTP_REQUEST_TIMEOUT:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, merchant says one of
@@ -392,12 +404,10 @@ handle_abort_finished (void *cls,
this should never happen, we should pass the JSON
reply to the application */
break;
- case MHD_HTTP_NOT_FOUND:
+ case MHD_HTTP_PRECONDITION_FAILED:
+ /* Our *payment* already succeeded fully. */
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
- /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the
- application */
break;
case MHD_HTTP_FAILED_DEPENDENCY:
TALER_MERCHANT_parse_error_details_ (json,
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-merchant] 55/277: fix fTBFS, (continued)
- [taler-merchant] 55/277: fix fTBFS, gnunet, 2020/07/05
- [taler-merchant] 61/277: rename fest to match new structure, gnunet, 2020/07/05
- [taler-merchant] 69/277: update pay logic, gnunet, 2020/07/05
- [taler-merchant] 74/277: DB API for /abort, gnunet, 2020/07/05
- [taler-merchant] 47/277: typo, gnunet, 2020/07/05
- [taler-merchant] 40/277: add PATCH /instances/ID command, gnunet, 2020/07/05
- [taler-merchant] 51/277: misc. fixes, gnunet, 2020/07/05
- [taler-merchant] 52/277: misc bugfixes, gnunet, 2020/07/05
- [taler-merchant] 64/277: work on POST /orders/ID/claim (unfinished), gnunet, 2020/07/05
- [taler-merchant] 80/277: implement /refund handling, gnunet, 2020/07/05
- [taler-merchant] 81/277: fix/complete inventory management logic,
gnunet <=
- [taler-merchant] 67/277: work on /pay API revision, gnunet, 2020/07/05
- [taler-merchant] 65/277: db implementation of claiming, gnunet, 2020/07/05
- [taler-merchant] 59/277: sql-ing for GET /orders, gnunet, 2020/07/05
- [taler-merchant] 70/277: work on /pay and /abort processing, gnunet, 2020/07/05
- [taler-merchant] 72/277: DB API for /abort, gnunet, 2020/07/05
- [taler-merchant] 77/277: POST /orders/ID/refund implementation, gnunet, 2020/07/05
- [taler-merchant] 79/277: backend code for /refund handling, gnunet, 2020/07/05
- [taler-merchant] 85/277: update testing logic for order CMDs, gnunet, 2020/07/05
- [taler-merchant] 89/277: fix benchmark FTBFS, gnunet, 2020/07/05
- [taler-merchant] 63/277: remove duplicate, gnunet, 2020/07/05