Skip to content

feat(admin): admins can create one-off custom appointments (#28463)#28502

Closed
anmolxlight wants to merge 2 commits intocalcom:mainfrom
anmolxlight:fix/issue-28463-admin-one-off-appointments
Closed

feat(admin): admins can create one-off custom appointments (#28463)#28502
anmolxlight wants to merge 2 commits intocalcom:mainfrom
anmolxlight:fix/issue-28463-admin-one-off-appointments

Conversation

@anmolxlight
Copy link

Fixes #28463. This adds the backend TRPC capability for system admins to create one-off custom appointments directly for users. It bypasses event types and provisions a one-off booking directly.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Ryan seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions github-actions bot added ✨ feature New feature or request 🚨 needs approval This feature request has not been reviewed yet by the Product Team and needs approval beforehand labels Mar 19, 2026
@pull-request-size pull-request-size bot added size/L and removed size/M labels Mar 19, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 27cd821e76

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +10 to +13
attendees: z.array(z.object({
email: z.string().email(),
name: z.string(),
})),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require a primary attendee in createCustomAppointment

If this mutation is called with attendees: [], it creates a booking that violates an existing invariant: several downstream consumers index the first attendee without guarding for empties, e.g. apps/web/components/booking/BookingListItem.tsx:1102-1104 and packages/features/ee/workflows/lib/getiCalEventAsString.ts:52-55. That means an admin-created booking with no attendees can later break booking pages or iCal/reminder generation instead of behaving like a normal appointment.

Useful? React with 👍 / 👎.

Comment on lines +54 to +57
create: input.attendees.map((attendee) => ({
name: attendee.name,
email: attendee.email,
timeZone: targetUser.timeZone,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Store each attendee's own timezone

For custom appointments with attendees outside the host's timezone, this persists every attendee as targetUser.timeZone, so attendee-facing reminders and webhook payloads will be localized incorrectly. We already use attendee.timeZone directly when formatting reminder content (packages/features/ee/workflows/lib/reminders/utils.ts:64-66) and building booking reminder attendees (apps/web/app/api/cron/bookingReminder/route.ts:105-110), so a New York attendee booked for a London host will see the wrong local time. Because the schema only accepts name and email, the caller has no way to provide the correct timezone.

Useful? React with 👍 / 👎.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/web/modules/ee/users/components/UsersTable.tsx">

<violation number="1" location="apps/web/modules/ee/users/components/UsersTable.tsx:417">
P2: Custom appointment creation does not validate that end time is after start time, allowing invalid inverted booking ranges to be submitted and persisted.</violation>

<violation number="2" location="apps/web/modules/ee/users/components/UsersTable.tsx:418">
P2: The attendee timezone is not collected or sent with the mutation. The handler will likely default all attendees to the host's timezone, causing reminders, iCal events, and webhook payloads to show incorrect local times for attendees in different timezones. Add a timezone field to the attendee input (defaulting to the browser's detected timezone if not explicitly provided).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/trpc/server/routers/viewer/admin/createCustomAppointment.schema.ts">

<violation number="1" location="packages/trpc/server/routers/viewer/admin/createCustomAppointment.schema.ts:7">
P2: UTC-only `z.string().datetime()` rejects valid ISO timestamps with numeric offsets, causing avoidable validation failures for client-supplied datetimes.</violation>

<violation number="2" location="packages/trpc/server/routers/viewer/admin/createCustomAppointment.schema.ts:10">
P1: The `attendees` array accepts an empty list. Bookings created with zero attendees will break downstream consumers that index `attendees[0]` without a guard (e.g., booking list rendering, iCal generation, workflow reminders). Add `.min(1)` to require at least one attendee.</violation>

<violation number="3" location="packages/trpc/server/routers/viewer/admin/createCustomAppointment.schema.ts:14">
P2: Missing cross-field validation allows invalid booking intervals where endTime is not after startTime.</violation>
</file>

<file name="packages/trpc/server/routers/viewer/admin/createCustomAppointment.handler.ts">

<violation number="1" location="packages/trpc/server/routers/viewer/admin/createCustomAppointment.handler.ts:52">
P2: Custom appointment creation stores `responses` as empty object, which can break downstream flows expecting `responses.email`/booker data.</violation>

<violation number="2" location="packages/trpc/server/routers/viewer/admin/createCustomAppointment.handler.ts:57">
P2: Every attendee is persisted with the host's timezone (`targetUser.timeZone`) instead of their own. Downstream reminder and webhook logic reads `attendee.timeZone` to localize times, so a New York attendee on a London host will receive incorrectly localized notifications. Add a `timeZone` field to each attendee in the schema and use it here.</violation>

<violation number="3" location="packages/trpc/server/routers/viewer/admin/createCustomAppointment.handler.ts:61">
P2: Per project Prisma guidelines, never use `include` — use `select` instead. `include: { attendees: true }` fetches all attendee columns, risking unnecessary data exposure from the tRPC endpoint. Replace with a `select` clause that explicitly lists only the needed booking and attendee fields.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@anmolxlight anmolxlight force-pushed the fix/issue-28463-admin-one-off-appointments branch from 3e85c55 to 106f732 Compare March 19, 2026 11:31
Copy link
Member

@romitg2 romitg2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, we'll remove 'needs approval' label from issue if we decide to add this feature. closing for now.

@romitg2 romitg2 closed this Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feature New feature or request 🚨 needs approval This feature request has not been reviewed yet by the Product Team and needs approval beforehand size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Admins: create one off custom appointments

3 participants