fix: degrade phone followups without calendar creds

This commit is contained in:
DMleadgen 2026-04-10 13:20:41 -06:00
parent bc2edc04f2
commit b67bb1e183
Signed by: matt
GPG key ID: C2720CF8CD701894
3 changed files with 62 additions and 23 deletions

View file

@ -5,6 +5,7 @@ import { requirePhoneAgentInternalAuth } from "@/app/api/internal/phone-calls/sh
import { import {
buildSameDayReminderWindow, buildSameDayReminderWindow,
createFollowupReminderEvent, createFollowupReminderEvent,
isGoogleCalendarConfigured,
} from "@/lib/google-calendar" } from "@/lib/google-calendar"
import { normalizePhoneE164, splitDisplayName } from "@/lib/phone-normalization" import { normalizePhoneE164, splitDisplayName } from "@/lib/phone-normalization"
@ -69,6 +70,7 @@ export async function POST(request: Request) {
const company = String(body.company || "").trim() const company = String(body.company || "").trim()
const reason = String(body.reason || "").trim() const reason = String(body.reason || "").trim()
const summaryText = String(body.summaryText || "").trim() const summaryText = String(body.summaryText || "").trim()
const calendarConfigured = isGoogleCalendarConfigured()
let startAt: Date let startAt: Date
let endAt: Date let endAt: Date
@ -90,24 +92,36 @@ export async function POST(request: Request) {
} }
} }
const reminder = await createFollowupReminderEvent({ if (kind === "scheduled" && !calendarConfigured) {
title: buildReminderTitle({ return NextResponse.json(
kind, { error: "Google Calendar follow-up scheduling is not configured" },
callerName, { status: 503 }
company, )
phone: normalizedPhone || String(body.phone || "").trim(), }
}),
description: buildReminderDescription({ const reminder = calendarConfigured
callerName, ? await createFollowupReminderEvent({
company, title: buildReminderTitle({
phone: normalizedPhone || String(body.phone || "").trim(), kind,
reason, callerName,
summaryText, company,
adminCallUrl, phone: normalizedPhone || String(body.phone || "").trim(),
}), }),
startAt, description: buildReminderDescription({
endAt, callerName,
}) company,
phone: normalizedPhone || String(body.phone || "").trim(),
reason,
summaryText,
adminCallUrl,
}),
startAt,
endAt,
})
: {
eventId: "",
htmlLink: "",
}
let contactProfileId: string | undefined let contactProfileId: string | undefined
if (normalizedPhone) { if (normalizedPhone) {
@ -135,19 +149,23 @@ export async function POST(request: Request) {
reminderRequestedAt: Date.now(), reminderRequestedAt: Date.now(),
reminderStartAt: startAt.getTime(), reminderStartAt: startAt.getTime(),
reminderEndAt: endAt.getTime(), reminderEndAt: endAt.getTime(),
reminderCalendarEventId: reminder.eventId, reminderCalendarEventId: reminder.eventId || undefined,
reminderCalendarHtmlLink: reminder.htmlLink || undefined, reminderCalendarHtmlLink: reminder.htmlLink || undefined,
reminderNote: reason || summaryText || undefined, reminderNote:
reason ||
summaryText ||
(!calendarConfigured ? "Manual follow-up reminder created without Google Calendar." : undefined),
}) })
return NextResponse.json({ return NextResponse.json({
success: true, success: true,
calendarConfigured,
reminder: { reminder: {
kind, kind,
startAt: startAt.toISOString(), startAt: startAt.toISOString(),
endAt: endAt.toISOString(), endAt: endAt.toISOString(),
eventId: reminder.eventId, eventId: reminder.eventId || null,
htmlLink: reminder.htmlLink, htmlLink: reminder.htmlLink || null,
}, },
call, call,
}) })

View file

@ -1,6 +1,9 @@
import { NextResponse } from "next/server" import { NextResponse } from "next/server"
import { requirePhoneAgentInternalAuth } from "@/app/api/internal/phone-calls/shared" import { requirePhoneAgentInternalAuth } from "@/app/api/internal/phone-calls/shared"
import { listFutureCallbackSlots } from "@/lib/google-calendar" import {
isGoogleCalendarConfigured,
listFutureCallbackSlots,
} from "@/lib/google-calendar"
export async function POST(request: Request) { export async function POST(request: Request) {
const authError = await requirePhoneAgentInternalAuth(request) const authError = await requirePhoneAgentInternalAuth(request)
@ -15,9 +18,18 @@ export async function POST(request: Request) {
? Math.min(body.limit, 5) ? Math.min(body.limit, 5)
: 3 : 3
if (!isGoogleCalendarConfigured()) {
return NextResponse.json({
success: true,
calendarConfigured: false,
slots: [],
})
}
const slots = await listFutureCallbackSlots(limit) const slots = await listFutureCallbackSlots(limit)
return NextResponse.json({ return NextResponse.json({
success: true, success: true,
calendarConfigured: true,
slots, slots,
}) })
} catch (error) { } catch (error) {

View file

@ -84,6 +84,15 @@ function getRequiredConfig() {
} }
} }
export function isGoogleCalendarConfigured() {
try {
getRequiredConfig()
return true
} catch {
return false
}
}
function getLocalDateTime(date: Date, timeZone = getTimeZone()): LocalDateTime { function getLocalDateTime(date: Date, timeZone = getTimeZone()): LocalDateTime {
const formatter = new Intl.DateTimeFormat("en-US", { const formatter = new Intl.DateTimeFormat("en-US", {
timeZone, timeZone,