/** * Cancel Tab * Only allowed if no orders have been submitted to kitchen (StatusID >= 1). * Releases the Stripe hold. * * POST: { TabID: int, UserID: int } */ try { requestData = deserializeJSON(toString(getHttpRequestData().content)); tabID = val(requestData.TabID ?: 0); userID = val(requestData.UserID ?: 0); if (tabID == 0) apiAbort({ "OK": false, "ERROR": "missing_TabID" }); if (userID == 0) apiAbort({ "OK": false, "ERROR": "missing_UserID" }); qTab = queryTimed(" SELECT ID, OwnerUserID, StatusID, StripePaymentIntentID, BusinessID FROM Tabs WHERE ID = :tabID LIMIT 1 ", { tabID: { value: tabID, cfsqltype: "cf_sql_integer" } }); if (qTab.recordCount == 0) apiAbort({ "OK": false, "ERROR": "tab_not_found" }); if (qTab.StatusID != 1) apiAbort({ "OK": false, "ERROR": "tab_not_open" }); if (qTab.OwnerUserID != userID) apiAbort({ "OK": false, "ERROR": "not_owner" }); // Check for submitted orders qSubmitted = queryTimed(" SELECT COUNT(*) AS Cnt FROM TabOrders tbo JOIN Orders o ON o.ID = tbo.OrderID WHERE tbo.TabID = :tabID AND tbo.ApprovalStatus = 'approved' AND o.StatusID >= 1 ", { tabID: { value: tabID, cfsqltype: "cf_sql_integer" } }); if (qSubmitted.Cnt > 0) { apiAbort({ "OK": false, "ERROR": "has_submitted_orders", "MESSAGE": "Tab has orders in progress. Close the tab instead of cancelling." }); } // Cancel Stripe PI if (len(trim(qTab.StripePaymentIntentID))) { cfhttp(method="POST", url="https://api.stripe.com/v1/payment_intents/#qTab.StripePaymentIntentID#/cancel", result="cancelResp") { cfhttpparam(type="header", name="Authorization", value="Bearer #application.stripeSecretKey#"); } } // Mark tab cancelled, release members queryTimed("UPDATE Tabs SET StatusID = 4, ClosedOn = NOW(), PaymentStatus = 'cancelled' WHERE ID = :tabID", { tabID: { value: tabID, cfsqltype: "cf_sql_integer" } }); queryTimed("UPDATE TabMembers SET StatusID = 3, LeftOn = NOW() WHERE TabID = :tabID AND StatusID = 1", { tabID: { value: tabID, cfsqltype: "cf_sql_integer" } }); apiAbort({ "OK": true, "MESSAGE": "Tab cancelled. Card hold released." }); } catch (any e) { apiAbort({ "OK": false, "ERROR": "server_error", "MESSAGE": e.message }); }