Portal local development: - Add BASE_PATH detection to all portal files (login, portal.js, menu-builder, station-assignment) - Allows portal to work at /biz.payfrit.com/ path locally Menu Builder fixes: - Fix duplicate template options in getForBuilder.cfm query - Filter template children by business ID with DISTINCT New APIs: - api/portal/myBusinesses.cfm - List businesses for logged-in user - api/stations/list.cfm - List KDS stations - api/menu/updateStations.cfm - Update item station assignments - api/setup/reimportBigDeans.cfm - Full Big Dean's menu import script Admin utilities: - Various debug and migration scripts for menu/template management - Beacon switching, category cleanup, modifier template setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
150 lines
4.4 KiB
Text
150 lines
4.4 KiB
Text
<cfsetting showdebugoutput="false">
|
|
<cfsetting enablecfoutputonly="true">
|
|
<cfsetting requesttimeout="120">
|
|
<cfcontent type="application/json; charset=utf-8" reset="true">
|
|
|
|
<cfscript>
|
|
/**
|
|
* Download Business Images
|
|
*
|
|
* Downloads logo and header images from external URLs and saves
|
|
* them to the uploads directory for a business.
|
|
*
|
|
* POST JSON:
|
|
* {
|
|
* "businessID": 123,
|
|
* "logoUrl": "https://example.com/logo.png",
|
|
* "headerUrl": "https://example.com/header.jpg"
|
|
* }
|
|
*
|
|
* Images are saved to:
|
|
* /uploads/logos/{BusinessID}.png
|
|
* /uploads/headers/{BusinessID}.jpg
|
|
*/
|
|
|
|
response = { "OK": false, "downloaded": [] };
|
|
|
|
try {
|
|
requestBody = toString(getHttpRequestData().content);
|
|
if (!len(requestBody)) {
|
|
throw(message="No request body provided");
|
|
}
|
|
|
|
data = deserializeJSON(requestBody);
|
|
|
|
if (!structKeyExists(data, "businessID") || val(data.businessID) == 0) {
|
|
throw(message="businessID is required");
|
|
}
|
|
|
|
businessID = val(data.businessID);
|
|
uploadsPath = expandPath("/uploads");
|
|
|
|
// Create uploads directories if they don't exist
|
|
logosPath = uploadsPath & "/logos";
|
|
headersPath = uploadsPath & "/headers";
|
|
|
|
if (!directoryExists(logosPath)) {
|
|
directoryCreate(logosPath);
|
|
}
|
|
if (!directoryExists(headersPath)) {
|
|
directoryCreate(headersPath);
|
|
}
|
|
|
|
// Download logo
|
|
if (structKeyExists(data, "logoUrl") && len(data.logoUrl)) {
|
|
logoUrl = data.logoUrl;
|
|
|
|
// Determine extension from URL or default to .png
|
|
ext = ".png";
|
|
if (findNoCase(".jpg", logoUrl) || findNoCase(".jpeg", logoUrl)) {
|
|
ext = ".jpg";
|
|
} else if (findNoCase(".gif", logoUrl)) {
|
|
ext = ".gif";
|
|
} else if (findNoCase(".webp", logoUrl)) {
|
|
ext = ".webp";
|
|
}
|
|
|
|
logoFile = logosPath & "/" & businessID & ext;
|
|
|
|
try {
|
|
cfhttp(url=logoUrl, method="GET", getasbinary="yes", timeout=30, result="logoResult");
|
|
|
|
if (logoResult.statusCode contains "200") {
|
|
fileWrite(logoFile, logoResult.fileContent);
|
|
arrayAppend(response.downloaded, {
|
|
"type": "logo",
|
|
"url": logoUrl,
|
|
"savedTo": "/uploads/logos/" & businessID & ext,
|
|
"size": len(logoResult.fileContent)
|
|
});
|
|
} else {
|
|
arrayAppend(response.downloaded, {
|
|
"type": "logo",
|
|
"url": logoUrl,
|
|
"error": "HTTP " & logoResult.statusCode
|
|
});
|
|
}
|
|
} catch (any e) {
|
|
arrayAppend(response.downloaded, {
|
|
"type": "logo",
|
|
"url": logoUrl,
|
|
"error": e.message
|
|
});
|
|
}
|
|
}
|
|
|
|
// Download header
|
|
if (structKeyExists(data, "headerUrl") && len(data.headerUrl)) {
|
|
headerUrl = data.headerUrl;
|
|
|
|
// Determine extension from URL or default to .jpg
|
|
ext = ".jpg";
|
|
if (findNoCase(".png", headerUrl)) {
|
|
ext = ".png";
|
|
} else if (findNoCase(".gif", headerUrl)) {
|
|
ext = ".gif";
|
|
} else if (findNoCase(".webp", headerUrl)) {
|
|
ext = ".webp";
|
|
}
|
|
|
|
headerFile = headersPath & "/" & businessID & ext;
|
|
|
|
try {
|
|
cfhttp(url=headerUrl, method="GET", getasbinary="yes", timeout=30, result="headerResult");
|
|
|
|
if (headerResult.statusCode contains "200") {
|
|
fileWrite(headerFile, headerResult.fileContent);
|
|
arrayAppend(response.downloaded, {
|
|
"type": "header",
|
|
"url": headerUrl,
|
|
"savedTo": "/uploads/headers/" & businessID & ext,
|
|
"size": len(headerResult.fileContent)
|
|
});
|
|
} else {
|
|
arrayAppend(response.downloaded, {
|
|
"type": "header",
|
|
"url": headerUrl,
|
|
"error": "HTTP " & headerResult.statusCode
|
|
});
|
|
}
|
|
} catch (any e) {
|
|
arrayAppend(response.downloaded, {
|
|
"type": "header",
|
|
"url": headerUrl,
|
|
"error": e.message
|
|
});
|
|
}
|
|
}
|
|
|
|
response.OK = true;
|
|
response.businessID = businessID;
|
|
|
|
} catch (any e) {
|
|
response.error = e.message;
|
|
if (len(e.detail)) {
|
|
response.errorDetail = e.detail;
|
|
}
|
|
}
|
|
|
|
writeOutput(serializeJSON(response));
|
|
</cfscript>
|