AI Voice Agent Backend
Module 13 · ai · intermediate
availability.js
// check_availability({ date: 'YYYY-MM-DD' }) → free slots that day
const s = $('Business Settings').first().json;
const db = $getWorkflowStaticData('global');
db.bookings = db.bookings ?? {};
const speak = (t) => DateTime.fromFormat(t, 'HH:mm').toFormat('h:mm a').replace(':00', '');
const speakList = (a) => (a.length <= 1 ? a.join('') : a.slice(0, -1).join(', ') + ' and ' + a.at(-1));
return $input.all().map(({ json }) => {
const date = String(json.args.date ?? '').trim();
const day = DateTime.fromISO(date);
let result;
if (!day.isValid) {
result = { ok: false, message: 'Which day would you like? Please tell me the date.' };
} else if (day.startOf('day') < DateTime.now().startOf('day')) {
result = { ok: false, message: 'That date is in the past. Which upcoming day works for you?' };
} else if (!s.open_days.includes(day.weekday)) {
result = { ok: false, date, available_slots: [], message: `We're closed on ${day.toFormat('cccc')}s. We're open Monday to Friday.` };
} else {
const all = [];
for (let h = s.open_hour; h < s.close_hour; h++) all.push(String(h).padStart(2, '0') + ':00');
const taken = Object.values(db.bookings).filter((b) => b.date === date).map((b) => b.time);
const free = all.filter((t) => !taken.includes(t));
result = free.length
? { ok: true, date, available_slots: free, message: `On ${day.toFormat('cccc, LLLL d')} we have ${speakList(free.map(speak))} available.` }
: { ok: true, date, available_slots: [], message: `Sorry, ${day.toFormat('cccc, LLLL d')} is fully booked. Would another day work?` };
}
return { json: { ...json, result } };
});