Skip to content

Comments

feat: implement global booking limits for users#25641

Open
Armadillidiid wants to merge 25 commits intocalcom:mainfrom
Armadillidiid:feat/global-user-booking-limit-v3
Open

feat: implement global booking limits for users#25641
Armadillidiid wants to merge 25 commits intocalcom:mainfrom
Armadillidiid:feat/global-user-booking-limit-v3

Conversation

@Armadillidiid
Copy link
Contributor

@Armadillidiid Armadillidiid commented Dec 5, 2025

What does this PR do?

This PR is a continuation of #14243 and #23100

Implements global booking limits that allows users to limit the total number of bookings for user event types from settings page.

Visual Demo

calcom-global-booking-limits-demo.mp4

Mandatory Tasks

  • I have self-reviewed the code
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - This is a new user-facing feature without developer API changes
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

Test Steps

  1. Enable Global Booking Limits

    • Navigate to Settings > My Account > Booking Limits
    • Toggle on "Limit booking frequency"
    • Set a limit (e.g., 2 bookings per day)
    • Click "Update"
  2. Test Limit Enforcement

    • Create or use an existing event type
    • Make bookings up to the global limit
    • Try again and notice that day/week/month/year isn't available and greyed out.
    • API ONLY: Attempt to call POST /api/book/event and verify it fails.
  3. Test Priority Hierarchy

    • Set different limits at user level vs event type level
    • Verify user limits take precedence for personal events
    • For team events, verify only team limits take precedence and user limits don't apply.
  4. Test Rescheduling

    • Reschedule an existing booking within the limit period
    • Verify the original booking doesn't count toward the limit

Expected Behavior

  • Users can set booking limits per day/week/month/year
  • Limits are enforced during booking creation
  • User availability calendar reflects limit status
  • Rescheduled bookings don't double-count against limits
  • Priority: User limits > Event type limits

Unit Tests

yarn test checkBookingLimits.test.ts

Integration Tests

yarn test global-booking-limits.integration-test.ts -- --integrationTestsOnly

Summary by cubic

Adds global user-level booking limits across a user's personal event types, with a dedicated My Account page and backend enforcement in availability and individual booking creation. Delivers CAL-1724 by blocking new bookings and hiding slots once a user's daily/weekly/monthly/yearly cap is reached.

  • New Features

    • Settings: New “Booking limits” tab under My Account; toggle and set global limits; save with validation and i18n copy.
    • Data: Store bookingLimits on User (JSON); TRPC get/update supports null to disable and validates order; shape validated on fetch.
    • Enforcement: Limits apply only to personal events (team events use team limits); reached periods show as busy and block new bookings; reschedules are excluded.
    • Infra: Repository query for accepted user bookings used by limit checks.
    • Tests: Added coverage for per-day, per-week, per-month, and per-year scenarios on individual events.
  • Migration

    • Run migration adding users.bookingLimits (JSONB).
    • No backfill needed; null means limits are off.

Written for commit 5fde653. Summary will update automatically on new commits.

@vercel
Copy link

vercel bot commented Dec 5, 2025

@Armadillidiid is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added community Created by Linear-GitHub Sync event-types area: event types, event-types Medium priority Created by Linear-GitHub Sync ✨ feature New feature or request and removed ✨ feature New feature or request Medium priority Created by Linear-GitHub Sync labels Dec 5, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2025

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

No release type found in pull request title "[WIP]: Implement global booking limits for users". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

@github-actions github-actions bot added ❗️ migrations contains migration files community Created by Linear-GitHub Sync event-types area: event types, event-types Medium priority Created by Linear-GitHub Sync ✨ feature New feature or request and removed event-types area: event types, event-types community Created by Linear-GitHub Sync labels Dec 5, 2025
@Armadillidiid Armadillidiid changed the title [WIP]: Implement global booking limits for users feat: implement global booking limits for users Dec 7, 2025
@Armadillidiid Armadillidiid marked this pull request as ready for review December 7, 2025 10:01
@Armadillidiid Armadillidiid requested a review from a team as a code owner December 7, 2025 10:01
@Armadillidiid Armadillidiid requested review from a team and Copilot December 7, 2025 10:01
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements global booking limits for users, allowing them to set booking frequency caps (per day/week/month/year) across all their personal event types from the My Account settings page. The feature includes database schema changes, TRPC endpoints for fetching and updating limits, enforcement in both availability checks and booking creation, and a comprehensive test suite.

Key changes:

  • Added bookingLimits JSON column to the User model with validation and enforcement logic
  • Implemented priority hierarchy where user global limits take precedence over event type limits for personal events, while team events remain isolated with their own team-level limits
  • Created new "Booking limits" settings page under My Account with toggle and form controls for configuring the limits

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/prisma/schema.prisma Added bookingLimits JSONB field to User model
packages/prisma/migrations/20250814170930_add_user_booking_limits/migration.sql Migration to add bookingLimits column to users table
packages/trpc/server/routers/viewer/me/updateProfile.schema.ts Added bookingLimits to profile update schema
packages/trpc/server/routers/viewer/me/updateProfile.handler.ts Implemented validation and persistence of booking limits with error handling
packages/trpc/server/routers/viewer/me/get.handler.ts Added bookingLimits retrieval and validation to user profile endpoint
packages/features/bookings/repositories/BookingRepository.ts Added getAllAcceptedUserBookings method to query personal bookings for limit enforcement
packages/features/bookings/lib/checkBookingLimits.ts Extended limit checking to support user-level limits with priority logic
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts Integrated global booking limits into booking creation flow for personal events
packages/features/busyTimes/lib/getBusyTimesFromLimits.ts Added getBusyTimesFromGlobalBookingLimits to mark time slots as busy when limits are reached
packages/features/availability/lib/getUserAvailability.ts Integrated global booking limits into availability calculation for personal events only
apps/web/modules/settings/my-account/booking-limits-view.tsx New settings page view for managing global booking limits
apps/web/components/settings/GlobalBookingLimitsController.tsx Form controller component with toggle, validation, and auto-save functionality
apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx Added "booking_limits" navigation tab (removed "conferencing" tab - likely unintentional)
apps/web/public/static/locales/en/common.json Added translation strings for global booking limits UI
packages/features/bookings/lib/handleNewBooking/test/global-booking-limits.integration-test.ts Comprehensive integration tests covering all limit intervals, priority rules, and edge cases
apps/web/test/lib/checkBookingLimits.test.ts Unit tests for limit checking service with priority hierarchy validation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

4 issues found across 30 files

Prompt for AI agents (all 4 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/features/bookings/lib/handleNewBooking/test/global-booking-limits.integration-test.ts">

<violation number="1" location="packages/features/bookings/lib/handleNewBooking/test/global-booking-limits.integration-test.ts:430">
P3: Typo in comment: &#39;firth&#39; should be &#39;fifth&#39;.</violation>
</file>

<file name="apps/web/app/(use-page-wrapper)/settings/(settings-layout)/my-account/booking-limits/page.tsx">

<violation number="1" location="apps/web/app/(use-page-wrapper)/settings/(settings-layout)/my-account/booking-limits/page.tsx:25">
P2: Callback URL should redirect to the current page (`/settings/my-account/booking-limits`) after login, not `/settings/my-account/general`. Following the pattern from `general/page.tsx`, each page should redirect back to itself.</violation>
</file>

<file name="apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx">

<violation number="1" location="apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx:43">
P1: The `conferencing` settings tab is being replaced rather than having `booking_limits` added as a new entry. The conferencing page still exists at `/settings/my-account/conferencing/` but will no longer be accessible via the navigation menu. Consider adding `booking_limits` as an additional entry instead of replacing `conferencing`.</violation>
</file>

<file name="packages/platform/libraries/tsconfig.json">

<violation number="1" location="packages/platform/libraries/tsconfig.json:15">
P2: Path mapping has mismatched wildcard syntax. The key `@calcom/web/public` lacks a wildcard but the value has `*`. For sub-path imports to resolve, both should use wildcards: `&quot;@calcom/web/public/*&quot;: [&quot;../../../apps/web/public/*&quot;]`.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

@github-actions
Copy link
Contributor

This PR has been marked as stale due to inactivity. If you're still working on it or need any help, please let us know or update the PR to keep it active.

@github-actions github-actions bot added Stale and removed Stale labels Dec 15, 2025
@github-actions
Copy link
Contributor

This PR has been marked as stale due to inactivity. If you're still working on it or need any help, please let us know or update the PR to keep it active.

This fixes Next.js module resolution error where bundled code couldn't
resolve translation files at runtime. For more info:
vercel/turborepo#4979 (comment)
- Added a new "Booking Limits" tab and page under My Account settings.
- Moved global booking limits UI from General to the new page.
- Updated i18n strings for booking limits and added a global
description.
- Removed booking limits controller from the General settings view.
Global user-level booking limits now apply exclusively to personal
events. Team events are governed by their own team booking limits,
preventing
unintended restriction by user-level limits.
@Armadillidiid Armadillidiid force-pushed the feat/global-user-booking-limit-v3 branch from 0b72cf4 to 5fde653 Compare December 28, 2025 06:27
@Armadillidiid Armadillidiid requested a review from a team as a code owner December 28, 2025 06:27
@github-actions
Copy link
Contributor

Devin AI is resolving merge conflicts

This PR has merge conflicts with the main branch. A Devin session has been created to automatically resolve them.

View Devin Session

Devin will:

  1. Merge the latest main into this branch
  2. Resolve any conflicts intelligently
  3. Run lint/type checks to ensure validity
  4. Push the resolved changes

If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself.

@github-actions
Copy link
Contributor

Devin AI is resolving merge conflicts

This PR has merge conflicts with the main branch. A Devin session has been created to automatically resolve them.

View Devin Session

Devin will:

  1. Merge the latest main into this branch
  2. Resolve any conflicts intelligently
  3. Run lint/type checks to ensure validity
  4. Push the resolved changes

If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself.

@github-actions github-actions bot removed the Stale label Jan 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community Created by Linear-GitHub Sync devin-conflict-resolution event-types area: event types, event-types ✨ feature New feature or request Medium priority Created by Linear-GitHub Sync ❗️ migrations contains migration files size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CAL-1724] Allow global booking limits

3 participants