From b08d3066dc01123b71912aa708d3e35e7e4c257b Mon Sep 17 00:00:00 2001 From: Jonathan Buchanan Date: Thu, 9 Jul 2020 17:34:40 -0400 Subject: handle insufficient stock in post orders --- .../taler-merchant-httpd_private-post-orders.c | 33 ++++++++++++++++++++++ src/lib/merchant_api_post_orders.c | 4 +++ src/testing/test_merchant_api.c | 31 ++++++++++++++++++++ 3 files changed, 68 insertions(+) (limited to 'src') diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c index 7fff7226..c97ac21c 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders.c +++ b/src/backend/taler-merchant-httpd_private-post-orders.c @@ -177,6 +177,9 @@ struct InventoryProduct }; +#define PRODUCT_OOS_OFFSET -3 + + /** * Execute the database transaction to setup the order. * @@ -249,6 +252,8 @@ execute_transaction (struct TMH_HandlerContext *hc, { /* qs == 0: lock acquisition failed due to insufficient stocks */ TMH_db->rollback (TMH_db->cls); + if (0 == qs) + qs = PRODUCT_OOS_OFFSET - i; /* indicate which product is causing the issue */ return qs; } } @@ -435,6 +440,34 @@ execute_order (struct MHD_Connection *connection, "serialization error, maybe try again?"); } + /* If we have a product that has insufficient quantities, + generate the details for the response. */ + if (PRODUCT_OOS_OFFSET >= qs) + { + unsigned int i = -qs + PRODUCT_OOS_OFFSET; + struct TALER_MERCHANTDB_ProductDetails pd; + + qs = TMH_db->lookup_product (TMH_db->cls, + hc->instance->settings.id, + inventory_products[i].product_id, + &pd); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_GONE, + "{s:s,s:I,s:I,s:o?}", + "product_id", + inventory_products[i].product_id, + "requested_quantity", + inventory_products[i].quantity, + "available_quantity", + pd.total_stock - pd.total_sold + - pd.total_lost, + "restock_expected", + (pd.next_restock.abs_value_us == 0) ? + NULL : + GNUNET_JSON_from_time_abs ( + pd.next_restock)); + } + { /* Hard error could be constraint violation, check if order already exists */ diff --git a/src/lib/merchant_api_post_orders.c b/src/lib/merchant_api_post_orders.c index 73815fdf..f4cc5290 100644 --- a/src/lib/merchant_api_post_orders.c +++ b/src/lib/merchant_api_post_orders.c @@ -146,6 +146,10 @@ handle_post_order_finished (void *cls, hr.ec = TALER_JSON_get_error_code (json); hr.hint = TALER_JSON_get_error_hint (json); break; + case MHD_HTTP_GONE: + /* The quantity of some product requested was not available. */ + // FIXME: parse the OutOfStockResponse. + break; default: /* unexpected response code */ hr.ec = TALER_JSON_get_error_code (json); diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c index 33de86ed..9fee2e3e 100644 --- a/src/testing/test_merchant_api.c +++ b/src/testing/test_merchant_api.c @@ -310,6 +310,21 @@ run (void *cls, "a product", "EUR:1", MHD_HTTP_NO_CONTENT), + TALER_TESTING_cmd_merchant_patch_product ("patch-products-p3", + merchant_url, + "product-3", + "a product", + json_object (), + "can", + "EUR:1", + json_object (), + json_object (), + 5, + 0, + json_object (), + GNUNET_TIME_relative_to_absolute ( + GNUNET_TIME_UNIT_MINUTES), + MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_lock_product ("lock-product-p3", merchant_url, "product-3", @@ -346,6 +361,22 @@ run (void *cls, "x-taler-bank", "unknown-product/2", ""), + TALER_TESTING_cmd_merchant_post_orders2 ( + "create-proposal-p3-not-enough-stock", + merchant_url, + MHD_HTTP_GONE, + "{\"max_fee\":\"EUR:0.5\",\ + \"order_id\":\"order-p3\",\ + \"refund_deadline\": {\"t_ms\": 0},\ + \"pay_deadline\": {\"t_ms\": \"never\" },\ + \"amount\":\"EUR:5.0\",\ + \"summary\": \"merchant-lib testcase\",\ + \"fulfillment_url\": \"https://example.com/\",\ + \"products\": [ {\"description\":\"ice cream\",\ + \"value\":\"{EUR:5}\"} ] }", + "x-taler-bank", + "product-3/24", + ""), TALER_TESTING_cmd_merchant_post_orders2 ("create-proposal-p3", merchant_url, MHD_HTTP_OK, -- cgit v1.2.3