This repository has been archived on 2026-03-21. You can view files and clone it, but cannot push or open issues or pull requests.
payfrit-biz/api/grants/create.cfm
John 16a3b7c9a3 Replace queryExecute with queryTimed across all endpoints for perf tracking
Converts 200+ endpoint files to use queryTimed() wrapper which tracks
DB query count and execution time. Restores perf dashboard files that
were accidentally moved to _scripts/. Includes portal UI updates.
2026-02-02 00:28:37 -08:00

167 lines
6.2 KiB
Text

<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfheader name="Cache-Control" value="no-store">
<cfinclude template="_grantUtils.cfm">
<cfscript>
data = {};
try {
raw = toString(getHttpRequestData().content);
if (len(trim(raw))) {
data = deserializeJSON(raw);
if (!isStruct(data)) data = {};
}
} catch (any e) { data = {}; }
ownerBusinessID = val(data.OwnerBusinessID ?: 0);
guestBusinessID = val(data.GuestBusinessID ?: 0);
servicePointID = val(data.ServicePointID ?: 0);
economicsType = trim(data.EconomicsType ?: "none");
economicsValue = val(data.EconomicsValue ?: 0);
eligibilityScope = trim(data.EligibilityScope ?: "public");
timePolicyType = trim(data.TimePolicyType ?: "always");
timePolicyData = structKeyExists(data, "TimePolicyData") ? data.TimePolicyData : "";
// Validate required fields
if (ownerBusinessID LTE 0 || guestBusinessID LTE 0 || servicePointID LTE 0) {
apiAbort({ "OK": false, "ERROR": "missing_params", "MESSAGE": "OwnerBusinessID, GuestBusinessID, and ServicePointID are required." });
}
if (ownerBusinessID == guestBusinessID) {
apiAbort({ "OK": false, "ERROR": "self_grant", "MESSAGE": "Cannot grant access to your own business." });
}
// Validate caller is the owner of OwnerBusinessID
callerUserID = val(structKeyExists(request, "UserID") ? request.UserID : 0);
if (callerUserID LTE 0) {
apiAbort({ "OK": false, "ERROR": "not_authenticated", "MESSAGE": "Authentication required." });
}
qOwner = queryTimed(
"SELECT UserID FROM Businesses WHERE ID = ? LIMIT 1",
[{ value = ownerBusinessID, cfsqltype = "cf_sql_integer" }],
{ datasource = "payfrit" }
);
if (qOwner.recordCount == 0 || qOwner.UserID != callerUserID) {
apiAbort({ "OK": false, "ERROR": "not_owner", "MESSAGE": "You are not the owner of this business." });
}
// Validate ServicePoint belongs to OwnerBusinessID
qSP = queryTimed(
"SELECT ID FROM ServicePoints WHERE ID = ? AND BusinessID = ? LIMIT 1",
[
{ value = servicePointID, cfsqltype = "cf_sql_integer" },
{ value = ownerBusinessID, cfsqltype = "cf_sql_integer" }
],
{ datasource = "payfrit" }
);
if (qSP.recordCount == 0) {
apiAbort({ "OK": false, "ERROR": "sp_not_owned", "MESSAGE": "Service point does not belong to your business." });
}
// Validate GuestBusiness exists
qGuest = queryTimed(
"SELECT ID FROM Businesses WHERE ID = ? LIMIT 1",
[{ value = guestBusinessID, cfsqltype = "cf_sql_integer" }],
{ datasource = "payfrit" }
);
if (qGuest.recordCount == 0) {
apiAbort({ "OK": false, "ERROR": "guest_not_found", "MESSAGE": "Guest business not found." });
}
// Check no active or pending grant exists for this combo
qExisting = queryTimed(
"SELECT ID FROM ServicePointGrants
WHERE OwnerBusinessID = ? AND GuestBusinessID = ? AND ServicePointID = ? AND StatusID IN (0, 1)
LIMIT 1",
[
{ value = ownerBusinessID, cfsqltype = "cf_sql_integer" },
{ value = guestBusinessID, cfsqltype = "cf_sql_integer" },
{ value = servicePointID, cfsqltype = "cf_sql_integer" }
],
{ datasource = "payfrit" }
);
if (qExisting.recordCount > 0) {
apiAbort({ "OK": false, "ERROR": "grant_exists", "MESSAGE": "An active or pending grant already exists for this service point and guest business." });
}
// Validate enum values
validEconomics = ["none", "flat_fee", "percent_of_orders"];
validEligibility = ["public", "employees", "guests", "internal"];
validTimePolicy = ["always", "schedule", "date_range", "event"];
if (!arrayFind(validEconomics, economicsType)) economicsType = "none";
if (!arrayFind(validEligibility, eligibilityScope)) eligibilityScope = "public";
if (!arrayFind(validTimePolicy, timePolicyType)) timePolicyType = "always";
// Generate UUID and InviteToken
newUUID = createObject("java", "java.util.UUID").randomUUID().toString();
inviteToken = lcase(hash(generateSecretKey("AES", 256), "SHA-256"));
// Serialize TimePolicyData
timePolicyJson = javaCast("null", "");
if (isStruct(timePolicyData) && !structIsEmpty(timePolicyData)) {
timePolicyJson = serializeJSON(timePolicyData);
} else if (isSimpleValue(timePolicyData) && len(trim(timePolicyData))) {
timePolicyJson = timePolicyData;
}
// Insert grant
queryTimed(
"INSERT INTO ServicePointGrants
(UUID, OwnerBusinessID, GuestBusinessID, ServicePointID, StatusID,
EconomicsType, EconomicsValue, EligibilityScope, TimePolicyType, TimePolicyData,
InviteToken, CreatedByUserID)
VALUES (?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?, ?)",
[
{ value = newUUID, cfsqltype = "cf_sql_varchar" },
{ value = ownerBusinessID, cfsqltype = "cf_sql_integer" },
{ value = guestBusinessID, cfsqltype = "cf_sql_integer" },
{ value = servicePointID, cfsqltype = "cf_sql_integer" },
{ value = economicsType, cfsqltype = "cf_sql_varchar" },
{ value = economicsValue, cfsqltype = "cf_sql_decimal" },
{ value = eligibilityScope, cfsqltype = "cf_sql_varchar" },
{ value = timePolicyType, cfsqltype = "cf_sql_varchar" },
{ value = timePolicyJson, cfsqltype = "cf_sql_varchar", null = isNull(timePolicyJson) },
{ value = inviteToken, cfsqltype = "cf_sql_varchar" },
{ value = callerUserID, cfsqltype = "cf_sql_integer" }
],
{ datasource = "payfrit" }
);
// Get the inserted grant ID
qNew = queryTimed(
"SELECT ID FROM ServicePointGrants WHERE UUID = ? LIMIT 1",
[{ value = newUUID, cfsqltype = "cf_sql_varchar" }],
{ datasource = "payfrit" }
);
grantID = qNew.ID;
// Record history
recordGrantHistory(
grantID = grantID,
action = "created",
actorUserID = callerUserID,
actorBusinessID = ownerBusinessID,
newData = {
"OwnerBusinessID": ownerBusinessID,
"GuestBusinessID": guestBusinessID,
"ServicePointID": servicePointID,
"EconomicsType": economicsType,
"EconomicsValue": economicsValue,
"EligibilityScope": eligibilityScope,
"TimePolicyType": timePolicyType
}
);
writeOutput(serializeJSON({
"OK": true,
"GrantID": grantID,
"UUID": newUUID,
"InviteToken": inviteToken,
"StatusID": 0,
"MESSAGE": "Grant created. Awaiting guest acceptance."
}));
</cfscript>