Add business timezone support for menu scheduling

- Add getTimeInZone() and getDayInZone() helpers in Application.cfm
- Update items.cfm and getForBuilder.cfm to use business timezone
- Menu availability now correctly respects each business's timezone

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2026-02-20 12:09:36 -08:00
parent 9e5770f131
commit 2c655a5963
3 changed files with 56 additions and 11 deletions

View file

@ -84,6 +84,35 @@ function toISO8601(d) {
return dateTimeFormat(utc, "yyyy-MM-dd'T'HH:nn:ss") & "Z"; return dateTimeFormat(utc, "yyyy-MM-dd'T'HH:nn:ss") & "Z";
} }
// Get current time in a specific timezone (returns "HH:mm:ss" string)
// Used for schedule filtering (menu availability, business hours)
function getTimeInZone(tz) {
if (isNull(tz) || !len(trim(tz))) tz = "America/Los_Angeles";
try {
var zoneId = createObject("java", "java.time.ZoneId").of(tz);
var zonedNow = createObject("java", "java.time.ZonedDateTime").now(zoneId);
var formatter = createObject("java", "java.time.format.DateTimeFormatter").ofPattern("HH:mm:ss");
return zonedNow.format(formatter);
} catch (any e) {
// Fallback to server time if timezone is invalid
return timeFormat(now(), "HH:mm:ss");
}
}
// Get current day of week in a specific timezone (returns 1-7, Sunday=1)
function getDayInZone(tz) {
if (isNull(tz) || !len(trim(tz))) tz = "America/Los_Angeles";
try {
var zoneId = createObject("java", "java.time.ZoneId").of(tz);
var zonedNow = createObject("java", "java.time.ZonedDateTime").now(zoneId);
// Java DayOfWeek: Monday=1, Sunday=7. Convert to CFML: Sunday=1, Monday=2...
var javaDow = zonedNow.getDayOfWeek().getValue();
return (javaDow mod 7) + 1; // Convert: Mon=2, Tue=3, ..., Sat=7, Sun=1
} catch (any e) {
return dayOfWeek(now());
}
}
// Determine request path // Determine request path
request._api_scriptName = ""; request._api_scriptName = "";
if (structKeyExists(cgi, "SCRIPT_NAME")) { if (structKeyExists(cgi, "SCRIPT_NAME")) {

View file

@ -60,13 +60,15 @@ try {
// Check for MenuID filter (optional - if provided, only return categories for that menu) // Check for MenuID filter (optional - if provided, only return categories for that menu)
menuID = structKeyExists(requestData, "MenuID") ? val(requestData.MenuID) : 0; menuID = structKeyExists(requestData, "MenuID") ? val(requestData.MenuID) : 0;
// Get business's default menu setting // Get business's default menu setting and timezone
defaultMenuID = 0; defaultMenuID = 0;
businessTimezone = "America/Los_Angeles";
try { try {
qBiz = queryTimed("SELECT DefaultMenuID FROM Businesses WHERE ID = :businessID", qBiz = queryTimed("SELECT DefaultMenuID, Timezone FROM Businesses WHERE ID = :businessID",
{ businessID: businessID }, { datasource: "payfrit" }); { businessID: businessID }, { datasource: "payfrit" });
if (qBiz.recordCount > 0 && !isNull(qBiz.DefaultMenuID)) { if (qBiz.recordCount > 0) {
defaultMenuID = val(qBiz.DefaultMenuID); if (!isNull(qBiz.DefaultMenuID)) defaultMenuID = val(qBiz.DefaultMenuID);
if (!isNull(qBiz.Timezone) && len(trim(qBiz.Timezone))) businessTimezone = qBiz.Timezone;
} }
} catch (any e) {} } catch (any e) {}
@ -95,9 +97,9 @@ try {
// Auto-select menu based on current time when no specific menu requested // Auto-select menu based on current time when no specific menu requested
if (menuID == 0 && qMenus.recordCount > 1) { if (menuID == 0 && qMenus.recordCount > 1) {
now = timeFormat(now(), "HH:mm"); currentTime = left(getTimeInZone(businessTimezone), 5); // "HH:mm"
dayOfWeek = dayOfWeek(now()); // 1=Sun, 2=Mon, ... 7=Sat currentDay = getDayInZone(businessTimezone); // 1=Sun, 2=Mon, ... 7=Sat
dayBit = 2 ^ (dayOfWeek - 1); // bitmask: 1=Sun, 2=Mon, 4=Tue, etc. dayBit = 2 ^ (currentDay - 1); // bitmask: 1=Sun, 2=Mon, 4=Tue, etc.
activeMenuIds = []; activeMenuIds = [];
for (m = 1; m <= qMenus.recordCount; m++) { for (m = 1; m <= qMenus.recordCount; m++) {
@ -111,7 +113,7 @@ try {
if (hasStart && hasEnd) { if (hasStart && hasEnd) {
startT = timeFormat(qMenus.StartTime[m], "HH:mm"); startT = timeFormat(qMenus.StartTime[m], "HH:mm");
endT = timeFormat(qMenus.EndTime[m], "HH:mm"); endT = timeFormat(qMenus.EndTime[m], "HH:mm");
if (now >= startT && now <= endT) { if (currentTime >= startT && currentTime <= endT) {
arrayAppend(activeMenuIds, qMenus.ID[m]); arrayAppend(activeMenuIds, qMenus.ID[m]);
} }
} else { } else {

View file

@ -48,9 +48,23 @@
<cfset apiAbort({ "OK": false, "ERROR": "missing_businessid", "MESSAGE": "BusinessID is required.", "DETAIL": "" })> <cfset apiAbort({ "OK": false, "ERROR": "missing_businessid", "MESSAGE": "BusinessID is required.", "DETAIL": "" })>
</cfif> </cfif>
<!--- Get current time and day for schedule filtering ---> <!--- Get business timezone for schedule filtering --->
<cfset currentTime = timeFormat(now(), "HH:mm:ss")> <cfset businessTimezone = "America/Los_Angeles">
<cfset currentDayID = dayOfWeek(now())> <cftry>
<cfset qTz = queryExecute(
"SELECT Timezone FROM Businesses WHERE ID = ?",
[ { value = BusinessID, cfsqltype = "cf_sql_integer" } ],
{ datasource = "payfrit" }
)>
<cfif qTz.recordCount GT 0 AND len(trim(qTz.Timezone))>
<cfset businessTimezone = qTz.Timezone>
</cfif>
<cfcatch><!--- Column might not exist yet, use default ---></cfcatch>
</cftry>
<!--- Get current time and day in business timezone for schedule filtering --->
<cfset currentTime = getTimeInZone(businessTimezone)>
<cfset currentDayID = getDayInZone(businessTimezone)>
<cfset menuList = []> <cfset menuList = []>
<cftry> <cftry>