Add per-tab ApprovalMode override for member order approval

- open.cfm: accept optional ApprovalMode param (0=auto, 1=manual, NULL=business default)
- addOrder.cfm: check tab ApprovalMode first, fall back to business TabApprovalRequired
- getActive.cfm: return resolved ApprovalRequired in tab response

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2026-02-25 11:44:06 -08:00
parent 623b94cb3d
commit ec3a15013b
3 changed files with 15 additions and 8 deletions

View file

@ -24,7 +24,7 @@ try {
// Get tab
qTab = queryTimed("
SELECT t.ID, t.StatusID, t.BusinessID, t.OwnerUserID, t.AuthAmountCents, t.RunningTotalCents,
b.TabApprovalRequired, b.TabAutoIncreaseThreshold
t.ApprovalMode, b.TabApprovalRequired, b.TabAutoIncreaseThreshold
FROM Tabs t
JOIN Businesses b ON b.ID = t.BusinessID
WHERE t.ID = :tabID LIMIT 1
@ -72,9 +72,12 @@ try {
taxRate = val(qBizTax.TaxRate);
taxCents = round(subtotalCents * taxRate);
// Determine approval status
// Determine approval status: per-tab ApprovalMode overrides business default
approvalStatus = "approved";
if (!isOwner && qTab.TabApprovalRequired == 1) {
requiresApproval = len(trim(qTab.ApprovalMode)) && isNumeric(qTab.ApprovalMode)
? val(qTab.ApprovalMode) == 1
: qTab.TabApprovalRequired == 1;
if (!isOwner && requiresApproval) {
approvalStatus = "pending";
}

View file

@ -19,7 +19,7 @@ try {
qTab = queryTimed("
SELECT t.ID, t.UUID, t.BusinessID, t.OwnerUserID, t.ServicePointID,
t.StatusID, t.AuthAmountCents, t.RunningTotalCents,
t.OpenedOn, t.LastActivityOn, t.PaymentStatus,
t.OpenedOn, t.LastActivityOn, t.PaymentStatus, t.ApprovalMode,
b.Name AS BusinessName, b.TabApprovalRequired,
tm.RoleID,
sp.Name AS ServicePointName,
@ -73,7 +73,9 @@ try {
"MemberCount": qMembers.MemberCount,
"PendingOrderCount": pendingCount,
"IsOwner": qTab.RoleID == 1,
"ApprovalRequired": qTab.TabApprovalRequired == 1
"ApprovalRequired": len(trim(qTab.ApprovalMode)) && isNumeric(qTab.ApprovalMode)
? val(qTab.ApprovalMode) == 1
: qTab.TabApprovalRequired == 1
}
});

View file

@ -32,6 +32,7 @@ try {
authAmount = val(requestData.AuthAmount ?: 0);
}
servicePointID = val(requestData.ServicePointID ?: 0);
approvalMode = structKeyExists(requestData, "ApprovalMode") ? val(requestData.ApprovalMode) : javaCast("null", "");
if (userID == 0) apiAbort({ "OK": false, "ERROR": "missing_UserID" });
if (businessID == 0) apiAbort({ "OK": false, "ERROR": "missing_BusinessID" });
@ -147,8 +148,8 @@ try {
// Insert tab
queryTimed("
INSERT INTO Tabs (UUID, BusinessID, OwnerUserID, ServicePointID, StatusID,
AuthAmountCents, StripePaymentIntentID, StripeCustomerID, OpenedOn, LastActivityOn)
VALUES (:uuid, :bizID, :userID, :spID, 1, :authCents, :piID, :custID, NOW(), NOW())
AuthAmountCents, StripePaymentIntentID, StripeCustomerID, ApprovalMode, OpenedOn, LastActivityOn)
VALUES (:uuid, :bizID, :userID, :spID, 1, :authCents, :piID, :custID, :approvalMode, NOW(), NOW())
", {
uuid: { value: tabUUID, cfsqltype: "cf_sql_varchar" },
bizID: { value: businessID, cfsqltype: "cf_sql_integer" },
@ -156,7 +157,8 @@ try {
spID: { value: servicePointID > 0 ? servicePointID : javaCast("null", ""), cfsqltype: "cf_sql_integer", null: servicePointID <= 0 },
authCents: { value: authAmountCents, cfsqltype: "cf_sql_integer" },
piID: { value: piData.id, cfsqltype: "cf_sql_varchar" },
custID: { value: stripeCustomerId, cfsqltype: "cf_sql_varchar" }
custID: { value: stripeCustomerId, cfsqltype: "cf_sql_varchar" },
approvalMode: { value: isNull(approvalMode) ? javaCast("null", "") : approvalMode, cfsqltype: "cf_sql_tinyint", null: isNull(approvalMode) }
});
// Get the tab ID