data = {}; try { raw = toString(getHttpRequestData().content); if (len(trim(raw))) { data = deserializeJSON(raw); if (!isStruct(data)) data = {}; } } catch (any e) { data = {}; } grantID = val(data.GrantID ?: 0); inviteToken = trim(data.InviteToken ?: ""); if (grantID LTE 0 && len(inviteToken) == 0) { apiAbort({ "OK": false, "ERROR": "missing_params", "MESSAGE": "GrantID or InviteToken is required." }); } callerUserID = val(structKeyExists(request, "UserID") ? request.UserID : 0); if (callerUserID LTE 0) { apiAbort({ "OK": false, "ERROR": "not_authenticated" }); } // Load grant by ID or token if (grantID GT 0) { qGrant = queryExecute( "SELECT g.*, b.UserID AS GuestOwnerUserID FROM ServicePointGrants g JOIN Businesses b ON b.ID = g.GuestBusinessID WHERE g.ID = ? LIMIT 1", [{ value = grantID, cfsqltype = "cf_sql_integer" }], { datasource = "payfrit" } ); } else { qGrant = queryExecute( "SELECT g.*, b.UserID AS GuestOwnerUserID FROM ServicePointGrants g JOIN Businesses b ON b.ID = g.GuestBusinessID WHERE g.InviteToken = ? LIMIT 1", [{ value = inviteToken, cfsqltype = "cf_sql_varchar" }], { datasource = "payfrit" } ); } if (qGrant.recordCount == 0) { apiAbort({ "OK": false, "ERROR": "not_found", "MESSAGE": "Grant not found." }); } if (qGrant.GuestOwnerUserID != callerUserID) { apiAbort({ "OK": false, "ERROR": "not_guest_owner", "MESSAGE": "Only the guest business owner can accept this invite." }); } if (qGrant.StatusID != 0) { statusLabels = { 1: "already active", 2: "declined", 3: "revoked" }; label = structKeyExists(statusLabels, qGrant.StatusID) ? statusLabels[qGrant.StatusID] : "not pending"; apiAbort({ "OK": false, "ERROR": "bad_state", "MESSAGE": "This grant is #label# and cannot be accepted." }); } // Accept: activate grant queryExecute( "UPDATE ServicePointGrants SET StatusID = 1, AcceptedOn = NOW(), AcceptedByUserID = ?, InviteToken = NULL WHERE ID = ?", [ { value = callerUserID, cfsqltype = "cf_sql_integer" }, { value = qGrant.ID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" } ); recordGrantHistory( grantID = qGrant.ID, action = "accepted", actorUserID = callerUserID, actorBusinessID = qGrant.GuestBusinessID, previousData = { "StatusID": 0 }, newData = { "StatusID": 1 } ); writeOutput(serializeJSON({ "OK": true, "GrantID": qGrant.ID, "MESSAGE": "Grant accepted. Service point access is now active." }));