From efdaab13e12d3f3772cca605359817c69322a9a4 Mon Sep 17 00:00:00 2001 From: Ashelyn Dawn Date: Mon, 20 Apr 2020 23:40:09 -0600 Subject: [PATCH] Update in-stock after purchase --- api/orders.js | 11 ++++++-- db/models/order.js | 14 +++++++++- db/sql/3-functions.sql | 61 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/api/orders.js b/api/orders.js index 1523112..23c6cc2 100644 --- a/api/orders.js +++ b/api/orders.js @@ -131,12 +131,19 @@ router.post('/current/checkout/verify', parseJSON, async (req, res) => { const {payment_intent} = await stripe.checkout.sessions.retrieve(session_id); const payment = await stripe.paymentIntents.retrieve(payment_intent) - if(payment.status === "succeeded"){ + // Handle this better? + if(payment.status !== "succeeded") + return res.json({status: payment.status}) + + try { order = await db.order.addPayment(currentTransaction, payment) + await db.session.clearCart(req.sessionObj.uuid) + } catch (err) { + console.error(err) + throw new Error("Unable to complete order") } - // TODO: Save stockchange record for purchase res.json({status: payment.status, order}) }) diff --git a/db/models/order.js b/db/models/order.js index 1030a48..0d20e48 100644 --- a/db/models/order.js +++ b/db/models/order.js @@ -150,7 +150,10 @@ order.addPayment = async function(transaction, paymentIntent){ if(!charge.paid) throw new Error("Charge was not paid") - return await dbUtil.executeFunction({ + // TODO: Put these both in a common transaction. Flag purchase for follow-up + // and/or send alert and/or refund on Stripe upon failure. + + const order = await dbUtil.executeFunction({ name: 'add_stripe_payment_to_transaction', params: [ transaction.uuid, @@ -161,4 +164,13 @@ order.addPayment = async function(transaction, paymentIntent){ returnType: 'order', single: true }) + + await dbUtil.executeFunction({ + name: 'deduct_stock_for_purchase', + params: [transaction.uuid], + returnType: 'item', + single: false + }) + + return order } diff --git a/db/sql/3-functions.sql b/db/sql/3-functions.sql index 3320237..eebf3e9 100644 --- a/db/sql/3-functions.sql +++ b/db/sql/3-functions.sql @@ -745,3 +745,64 @@ begin return query select * from sos.v_session where session_uuid = _session_uuid; end; $function$; + +create or replace function sos.deduct_stock_for_purchase(_transaction_uuid uuid) + returns setof sos.v_item + language plpgsql +as $function$ +declare + _item_uuids uuid[]; + _cart_uuid uuid; + _item_uuid uuid; + _item_count integer; + _stockchange_uuid uuid; +begin + -- Get cart uuid (and check completed) + select transaction_cart_uuid into _cart_uuid + from sos."transaction" + where transaction_uuid = _transaction_uuid + and transaction_payment_state = 'completed'; + + -- Double check we got the cart + -- (Will be null if transaction is not complete) + if _cart_uuid is null then + raise 'Transaction not complete'; + end if; + + -- Get item array + _item_uuids := ARRAY( + select cart_item_item_uuid from sos."cart_item" + where cart_item_cart_uuid = _cart_uuid + ); + + -- Make stock-change record for each item + foreach _item_uuid in array _item_uuids loop + select cart_item_count into _item_count from sos."cart_item" + where cart_item_cart_uuid = _cart_uuid + and cart_item_item_uuid = _item_uuid; + + insert into sos."item_stockchange" ( + stockchange_type, + stockchange_item_uuid, + stockchange_change, + stockchange_direction + ) values ( + 'purchase', + _item_uuid, + _item_count, + 'subtracted' + ) returning stockchange_uuid into _stockchange_uuid; + + insert into sos."item_stockchange_purchase" ( + stockchange_uuid, + stockchange_type, + stockchange_transaction_uuid + ) values ( + _stockchange_uuid, + 'purchase', + _transaction_uuid + ); + end loop; + + return query select * from sos.v_item where item_uuid = any(_item_uuids); +end; $function$;