Skip to content

Conversation

giripatel
Copy link
Contributor

@giripatel giripatel commented Jun 23, 2025

What does this PR do?

This feature introduces a new webhook event that triggers when a reservation expires. It allows external systems to receive real-time notifications about expired reservations, enabling better automation and integration workflows.

Key Highlights:

  • Event Trigger: Fires automatically upon reservation expiration.

  • Payload: Includes reservation details such as id, timestamps, and status.

  • Integration: Can be configured via existing webhook settings.

  • Fixes feature: expired reservation tracking #21845

  • Fixes CAL-5934

Visual Demo (For contributors especially)

A visual demonstration is strongly recommended, for both the original and new change (video / image - any one).

Video Demo (if applicable):

  • Show screen recordings of the issue or feature.
  • Demonstrate how to reproduce the issue, the behavior before and after the change.

Image Demo of Final Payload:

Screenshot from 2025-06-24 04-27-18

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. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  1. Add or configure a webhook URL in the system to listen for "Reservation Expired" events.
  2. Create a reservation with a known expiration time.
  3. Allow the reservation to expire naturally (do not manually cancel it).
  4. Ensure that the system processes the slot release.
  5. The event type is correct: "RESERVATION_EXPIRED".
  6. The payload includes accurate and complete reservation data.
  • Are there environment variables that should be set?

No

  • What are the minimal test data to have?

Available Time slot

  • What is expected (happy path) to have (input and output)?

Configured Event trigger with reservation slot data.


Summary by cubic

Added a new webhook event that triggers when a reservation expires, allowing external systems to get notified in real time.

  • New Features
    • Sends a RESERVATION_EXPIRED webhook with reservation details when a slot expires.
    • Updated docs, translations, and webhook configuration to support the new event.

- Add RESERVATION_EXPIRED enum
- create one to many relationship between SelectedSlots and WebhookScheduledTriggers
@giripatel giripatel requested a review from a team as a code owner June 23, 2025 23:15
Copy link

vercel bot commented Jun 23, 2025

@giripatel 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 Jun 23, 2025
@graphite-app graphite-app bot requested a review from a team June 23, 2025 23:15
@github-actions github-actions bot added api area: API, enterprise API, access token, OAuth platform Anything related to our platform plan ✨ feature New feature or request ❗️ migrations contains migration files and removed ✨ feature New feature or request platform Anything related to our platform plan api area: API, enterprise API, access token, OAuth community Created by Linear-GitHub Sync labels Jun 23, 2025
@dosubot dosubot bot added i18n area: i18n, translations webhooks area: webhooks, callback, webhook payload ✨ feature New feature or request labels Jun 23, 2025
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.

cubic found 1 issue across 48 files. Review it in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

payload String
startAfter DateTime
retryCount Int @default(0)
createdAt DateTime? @default(now())
Copy link
Contributor

Choose a reason for hiding this comment

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

Rule violated: Prevent Direct NOW() Usage in Database Queries

  Uses now() without explicit UTC conversion, violating rule against unspecific NOW() usage and risking non-UTC timestamps.
Suggested change
createdAt DateTime? @default(now())
createdAt DateTime? @default(dbgenerated("(now() at time zone 'utc')"))

Copy link

graphite-app bot commented Jun 23, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (06/23/25)

1 reviewer was added to this PR based on Keith Williams's automation.

"Add community label" took an action on this PR • (06/23/25)

1 label was added to this PR based on Keith Williams's automation.

@kart1ka
Copy link
Contributor

kart1ka commented Jun 24, 2025

Hey @giripatel. Thanks for the PR. Could you please add a full loom video showing your feature?
Also a unit test seems to be failing. Pls fix it.

@giripatel
Copy link
Contributor Author

Hey @giripatel. Thanks for the PR. Could you please add a full loom video showing your feature? Also a unit test seems to be failing. Pls fix it.

Hey @kart1ka ,

Please find the demo video for the PR linked below:
https://www.loom.com/share/af4a4c676c12435d96369c35c4815860?sid=5c595cc2-0752-417f-aa57-406f7ae24a72

Let me know if you need any further information or clarification regarding the PR.

Thanks!

@giripatel giripatel requested a review from a team July 3, 2025 22:29
@giripatel giripatel requested a review from a team as a code owner July 3, 2025 22:29
@github-actions github-actions bot added api area: API, enterprise API, access token, OAuth platform Anything related to our platform plan labels Jul 3, 2025
@giripatel
Copy link
Contributor Author

Hey @kart1ka ,

Could you please take a moment to review it and let me know if any changes are needed from my side?

Thank you!
CC: @PeerRich @Udit-takkar

Copy link
Contributor

@kart1ka kart1ka left a comment

Choose a reason for hiding this comment

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

Left few comments.

@kart1ka kart1ka marked this pull request as draft July 9, 2025 17:12
@kart1ka
Copy link
Contributor

kart1ka commented Jul 9, 2025

@giripatel Pls also resolve merge conflicts and fix unit test.
Making it draft. Feel free to rfr once the comments are addressed.

@giripatel
Copy link
Contributor Author

Hey @kart1ka ,

I'm not encountering the test failure on my local setup. Could you help me investigate the issue?

Evidence:
Screenshot from 2025-07-11 00-54-18

Copy link
Contributor

@kart1ka kart1ka left a comment

Choose a reason for hiding this comment

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

Left a few comments

@kart1ka
Copy link
Contributor

kart1ka commented Jul 13, 2025

Pls also try to resolve the merge conflicts and add a loom video of the feature.

Copy link
Contributor

coderabbitai bot commented Jul 23, 2025

Walkthrough

This change introduces support for tracking and handling expired reservations across the application. It adds a new "reservation_expired" localization string to all supported language resource files. The webhook system is extended to recognize a new trigger event, RESERVATION_EXPIRED, which is reflected in both backend constants and documentation. Database migrations update the schema by adding and then removing a foreign key relation for selected slots and by extending the webhook trigger events enum. The core slot reservation handler is refactored to fetch additional event type details, perform asynchronous upserts for reserved slots, and schedule reservation expiration webhooks for each user. Supporting utilities and tests are updated to accommodate these changes, including the introduction of a new scheduling function for reservation expiration triggers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

  • Complexity: The review spans multiple domains—localization, database migrations, backend logic, webhook infrastructure, and tests. The core slot reservation handler logic is notably refactored to introduce asynchronous flows and webhook scheduling, requiring careful review for concurrency, correctness, and integration with new trigger types. The new scheduling utility and related test changes also add to the review depth, while the large number of localization file updates, though individually simple, increase the scope.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/features/webhooks/components/WebhookForm.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

packages/features/webhooks/lib/constants.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

packages/features/webhooks/lib/scheduleTrigger.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

  • 2 others

Note

⚡️ Unit Test Generation - Beta

CodeRabbit's unit test generation is now available in Beta! Automatically generate comprehensive unit tests for your code changes, ensuring better test coverage and catching edge cases you might miss. Our AI analyzes your code structure and creates tests that follow best practices and your project's testing patterns. Learn more here, or just try it under ✨ Finishing Touches.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@giripatel
Copy link
Contributor Author

Pls also try to resolve the merge conflicts and add a loom video of the feature.

Hey @kart1ka , Please find the loom video of the feature below.

https://www.loom.com/share/af4a4c676c12435d96369c35c4815860?sid=5c595cc2-0752-417f-aa57-406f7ae24a72

@giripatel giripatel marked this pull request as ready for review July 23, 2025 21:28
@giripatel giripatel requested a review from kart1ka July 23, 2025 21:28
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: 5

🔭 Outside diff range comments (3)
packages/features/webhooks/components/WebhookForm.tsx (1)

55-62: Keep alphabetical order & add missing translation for “reservation_expired”

The options array should remain sorted by label to minimize merge conflicts. I’ve reordered the three entries below. Additionally, our checks show that the Bengali locale is missing the new key—please add it to avoid fallback to raw text.

• Reorder snippet in packages/features/webhooks/components/WebhookForm.tsx:

-    { value: WebhookTriggerEvents.OOO_CREATED,      label: "ooo_created" },
-    { value: WebhookTriggerEvents.RESERVATION_EXPIRED, label: "reservation_expired" },
-    { value: WebhookTriggerEvents.RECORDING_READY,   label: "recording_ready" },
+    { value: WebhookTriggerEvents.OOO_CREATED,      label: "ooo_created" },
+    { value: WebhookTriggerEvents.RECORDING_READY,   label: "recording_ready" },
+    { value: WebhookTriggerEvents.RESERVATION_EXPIRED, label: "reservation_expired" },

• Missing translation key:

  • apps/web/public/static/locales/bn/common.json

Please add a "reservation_expired": "your translated string" entry in that file.

docs/developing/guides/automation/webhooks.mdx (1)

24-37: Missing bullet for the new trigger → documentation inconsistent

The numbered list under “Event triggers” still omits Reservation Expired, causing a discrepancy with the table below and with the product UI.

@@
         You can choose which specific triggers to listen to. Currently available triggers include:
         - `Booking Cancelled`
         - `Booking Created`
         - `Booking Rescheduled`
         - `Booking Rejected`
         - `Booking Requested`
         - `Booking Payment Initiated`
         - `Booking Paid`
         - `Meeting Started`
         - `Recording Ready`
         - `Form Submitted`
         - `Meeting Ended`
         - `Instant Meeting Created`
+        - `Reservation Expired`
packages/trpc/server/routers/viewer/slots/reserveSlot.handler.ts (1)

150-155: Fix misleading error message in catch block.

The error message "Event type not found" is incorrect here since the event type existence was already validated at line 53. This catch block handles failures from slot reservation or webhook scheduling operations.

Apply this fix to provide a more accurate error message:

    } catch {
      throw new TRPCError({
-        message: "Event type not found",
-        code: "NOT_FOUND",
+        message: "Failed to reserve slot or schedule webhook",
+        code: "INTERNAL_SERVER_ERROR",
      });
    }
♻️ Duplicate comments (1)
packages/features/webhooks/lib/scheduleTrigger.ts (1)

296-307: Improve the fragile webhook trigger search logic.

The current implementation using JSON string manipulation is unreliable because:

  1. JSON.stringify doesn't guarantee consistent property ordering
  2. The contains search could match unrelated payloads
  3. String slicing assumes specific JSON formatting

Regarding the past review comment about updating existing triggers: this is necessary to handle reservation time extensions or modifications while maintaining a single trigger per slot.

Consider using a more robust approach:

-    const { id, releaseAt, isSeat, ...rest } = slot;
-    const restString = JSON.stringify(rest);
-    const searchString = restString.slice(1, -1);
-
-    const isWebhookScheduledTriggerExists = await prisma.webhookScheduledTriggers.findFirst({
-      where: {
-        payload: {
-          contains: searchString,
-        },
-      },
-    });
+    const isWebhookScheduledTriggerExists = await prisma.webhookScheduledTriggers.findFirst({
+      where: {
+        AND: [
+          { payload: { contains: `"uid":"${slot.uid}"` } },
+          { payload: { contains: `"eventTypeId":${slot.eventTypeId}` } },
+          { payload: { contains: `"userId":${slot.userId}` } },
+          { payload: { contains: `"triggerEvent":"${triggerEvent}"` } },
+        ],
+      },
+    });

Alternatively, consider adding a unique identifier field to the webhook scheduled triggers table for more reliable lookups.

🧹 Nitpick comments (11)
apps/web/public/static/locales/fr/common.json (1)

3334-3334: Consider keeping keys alphabetically grouped for maintainability

The French translation looks good, but the new key is appended far away from the existing reservation_* group (around lines 530-545). Moving it near related keys keeps the JSON easier to scan and reduces merge-conflict odds when other locales get updated.

@@
   "booking_paid": "Réservation payée",
   "reservation_expired": "Réservation expirée",
   "ooo_created": "Absence créée",
apps/web/public/static/locales/ro/common.json (1)

3334-3334: Translation tense likely wrong – use past tense like the other “expired” strings.

Elsewhere in this locale file you translate “request_is_expired” as “Acea solicitare a expirat.”
For consistency and correctness, reservation_expired should probably be

"reservation_expired": "Rezervarea a expirat"

Current “Rezervarea expiră” means “is expiring”, not “has expired”.
Please align with the past-tense pattern.

apps/web/public/static/locales/ru/common.json (1)

3334-3334: Confirm new key is present in all locale files

"reservation_expired": "Бронь истекла", looks good and follows the existing style.
Please make sure the same key is added (with proper translations or a sensible fallback) to every other locale file to avoid i18n fall-back warnings at runtime.

apps/web/public/static/locales/eu/common.json (1)

3334-3334: Duplicate-key / placement sanity-check

A new entry

"reservation_expired": "Erreserba iraungita",

has been appended far down in the file.
Two quick things to verify before merging:

  1. Make sure the key name isn’t already present elsewhere in this JSON – duplicate keys silently override in most JS loaders and are painful to trace.
  2. Keep the roughly alphabetical grouping we follow in the other locale files so that translators don’t have to hunt; if this key belongs around the other reservation_ messages higher up, consider moving it there.

No functional changes required if the above points are confirmed.

apps/web/public/static/locales/he/common.json (1)

3334-3334: Translation is understandable but sounds unnatural – consider using “הזמנה פקעה”

“הזמנה פגה” is grammatically correct, yet native speakers usually phrase an expired reservation as “הזמנה פקעה” or the fuller “תוקף ההזמנה פג/פקע”.
Replacing the wording will feel more natural in the UI.

-  "reservation_expired": "הזמנה פגה"
+  "reservation_expired": "הזמנה פקעה"
apps/web/public/static/locales/sv/common.json (1)

3334-3334: Swedish phrasing feels off – suggest a more natural translation

“Bokning utgången” reads awkwardly in Swedish (literally “booking expired”).
Common phrasing would be e.g. "Bokningen har löpt ut" or "Reservationen har löpt ut" to include the verb.

-  "reservation_expired": "Bokning utgången",
+  "reservation_expired": "Bokningen har löpt ut",

This keeps consistency with other keys that form complete sentences.
Double-check any UI where the string appears for length/truncation.

packages/prisma/migrations/20250723210656_remove_selected_slots_realtion_with_webhook_triggers/migration.sql (1)

7-11: Minor: misspelled directory name & defensive SQL

The migration folder is named ...remove_selected_slots_realtion... – “relation” is misspelled. Consistency helps when scanning migration history.

For idempotency in dev/provisional environments, consider adding IF EXISTS to the DROP CONSTRAINT and DROP COLUMN statements. It prevents the entire migration from failing when the previous migration never ran (common in fresh DB snapshots).

Example:

-ALTER TABLE "WebhookScheduledTriggers" DROP CONSTRAINT "WebhookScheduledTriggers_selectedSlotId_fkey";
-ALTER TABLE "WebhookScheduledTriggers" DROP COLUMN "selectedSlotId";
+ALTER TABLE "WebhookScheduledTriggers" 
+  DROP CONSTRAINT IF EXISTS "WebhookScheduledTriggers_selectedSlotId_fkey",
+  DROP COLUMN IF EXISTS "selectedSlotId";
apps/web/public/static/locales/id/common.json (1)

168-169: Use the standard Indonesian spelling “kedaluwarsa”.

“Kedaluwarsa” is the KBBI-preferred form; “kadaluarsa” is colloquial. Updating it keeps terminology consistent with formal wording used in the rest of the locale file.

-  "reservation_expired": "Reservasi kadaluarsa"
+  "reservation_expired": "Reservasi kedaluwarsa"
apps/web/public/static/locales/az/common.json (1)

3334-3334: Confirm translation & i18n consistency for the new “reservation_expired” string
Good to see the new key landed, but please double-check:

  1. Wording – does “Rezervasiyanın müddəti bitmişdir” match the tone/style used for similar past-tense system states (e.g. “booking_cancelled”)?
  2. Pluralisation – this message is singular; if any UI shows the state in bulk contexts you might later need plural forms.
  3. Alphabetical / grouped ordering – we usually keep new keys clustered with other “reservation_…” strings to minimise merge noise across locales.

If all three are intentional, no further action needed.

packages/features/webhooks/lib/constants.ts (1)

5-24: Consider alphabetising / de-duplicating the core array for long-term maintainability
As this list keeps growing, manual ordering makes it easy to introduce duplicates or miss events when scanning the file. A simple alphabetical sort (or an automated utility that derives the list from WebhookTriggerEvents and filters by prefix) would make future reviews cheaper and errors less likely.

packages/features/webhooks/lib/scheduleTrigger.ts (1)

334-334: Use the logger instance instead of console.error.

For consistency with the rest of the file and better error tracking, use the existing logger instance.

-    console.error("Error scheduling webhook trigger (create/update)", error);
+    log.error("Error scheduling webhook trigger (create/update)", safeStringify(error));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b88603 and 8bfb139.

📒 Files selected for processing (51)
  • apps/web/public/static/locales/ar/common.json (1 hunks)
  • apps/web/public/static/locales/az/common.json (1 hunks)
  • apps/web/public/static/locales/bg/common.json (1 hunks)
  • apps/web/public/static/locales/ca/common.json (2 hunks)
  • apps/web/public/static/locales/cs/common.json (1 hunks)
  • apps/web/public/static/locales/da/common.json (1 hunks)
  • apps/web/public/static/locales/de/common.json (1 hunks)
  • apps/web/public/static/locales/el/common.json (1 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • apps/web/public/static/locales/es-419/common.json (1 hunks)
  • apps/web/public/static/locales/es/common.json (1 hunks)
  • apps/web/public/static/locales/et/common.json (1 hunks)
  • apps/web/public/static/locales/eu/common.json (1 hunks)
  • apps/web/public/static/locales/fi/common.json (1 hunks)
  • apps/web/public/static/locales/fr/common.json (1 hunks)
  • apps/web/public/static/locales/he/common.json (1 hunks)
  • apps/web/public/static/locales/hr/common.json (1 hunks)
  • apps/web/public/static/locales/hu/common.json (1 hunks)
  • apps/web/public/static/locales/id/common.json (1 hunks)
  • apps/web/public/static/locales/it/common.json (1 hunks)
  • apps/web/public/static/locales/ja/common.json (1 hunks)
  • apps/web/public/static/locales/km/common.json (1 hunks)
  • apps/web/public/static/locales/ko/common.json (1 hunks)
  • apps/web/public/static/locales/lv/common.json (1 hunks)
  • apps/web/public/static/locales/nl/common.json (1 hunks)
  • apps/web/public/static/locales/no/common.json (1 hunks)
  • apps/web/public/static/locales/pl/common.json (1 hunks)
  • apps/web/public/static/locales/pt-BR/common.json (1 hunks)
  • apps/web/public/static/locales/pt/common.json (1 hunks)
  • apps/web/public/static/locales/ro/common.json (1 hunks)
  • apps/web/public/static/locales/ru/common.json (1 hunks)
  • apps/web/public/static/locales/sk-SK/common.json (1 hunks)
  • apps/web/public/static/locales/sk/common.json (1 hunks)
  • apps/web/public/static/locales/sr/common.json (1 hunks)
  • apps/web/public/static/locales/sv/common.json (1 hunks)
  • apps/web/public/static/locales/ta/common.json (1 hunks)
  • apps/web/public/static/locales/tr/common.json (1 hunks)
  • apps/web/public/static/locales/uk/common.json (1 hunks)
  • apps/web/public/static/locales/vi/common.json (1 hunks)
  • apps/web/public/static/locales/zh-CN/common.json (1 hunks)
  • apps/web/public/static/locales/zh-TW/common.json (1 hunks)
  • docs/developing/guides/automation/webhooks.mdx (1 hunks)
  • packages/features/schedules/components/Schedule.tsx (0 hunks)
  • packages/features/webhooks/components/WebhookForm.tsx (1 hunks)
  • packages/features/webhooks/lib/constants.ts (1 hunks)
  • packages/features/webhooks/lib/scheduleTrigger.ts (2 hunks)
  • packages/prisma/migrations/20250623204508_add_reservation_expired_webhook/migration.sql (1 hunks)
  • packages/prisma/migrations/20250723210656_remove_selected_slots_realtion_with_webhook_triggers/migration.sql (1 hunks)
  • packages/prisma/schema.prisma (1 hunks)
  • packages/trpc/server/routers/viewer/slots/reserveSlot.handler.test.ts (1 hunks)
  • packages/trpc/server/routers/viewer/slots/reserveSlot.handler.ts (4 hunks)
💤 Files with no reviewable changes (1)
  • packages/features/schedules/components/Schedule.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code. Functions like .add, .diff, .isBefore, and .isAfter are slow, especially in timezone mode. Prefer .utc() for better performance. Where possible, replace with native Date and direct .valueOf() comparisons for faster execution. Recommend using native methods or Day.js .utc() consistently in hot paths like loops.

Files:

  • packages/trpc/server/routers/viewer/slots/reserveSlot.handler.test.ts
  • packages/features/webhooks/components/WebhookForm.tsx
  • packages/features/webhooks/lib/constants.ts
  • packages/trpc/server/routers/viewer/slots/reserveSlot.handler.ts
  • packages/features/webhooks/lib/scheduleTrigger.ts
🧠 Learnings (23)
apps/web/public/static/locales/en/common.json (2)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-21T13:54:11.770Z
Learning: Applies to docs/api-reference/v2/openapi.json : When docs changes are made in /docs/api-reference/v2/openapi.json, ensure the following: 'summary' fields are written in proper American english.

apps/web/public/static/locales/sr/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/zh-TW/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/bg/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/km/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

packages/trpc/server/routers/viewer/slots/reserveSlot.handler.test.ts (1)

Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.

apps/web/public/static/locales/sk/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

packages/features/webhooks/lib/constants.ts (1)

Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.

apps/web/public/static/locales/es/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/lv/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/sv/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/it/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/az/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/ar/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/ro/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/pt/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/es-419/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/cs/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/hr/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

apps/web/public/static/locales/pl/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

packages/trpc/server/routers/viewer/slots/reserveSlot.handler.ts (3)

Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.

Learnt from: vijayraghav-io
PR: #21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The upsertSelectedCalendarsForEventTypeIds method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like @@unique([outlookSubscriptionId, eventTypeId]) should not be applied as they would prevent this intended functionality.

Learnt from: vijayraghav-io
PR: #21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like @@unique([outlookSubscriptionId, eventTypeId]) should not be added as they would break this subscription sharing functionality.

apps/web/public/static/locales/ca/common.json (1)

Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.233Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.

packages/features/webhooks/lib/scheduleTrigger.ts (3)

Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.

Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:50-60
Timestamp: 2025-07-18T17:54:04.613Z
Learning: For Microsoft Graph webhook handlers, when dealing with internal configuration errors (like missing MICROSOFT_WEBHOOK_TOKEN), it's better to return 200 OK with errors tracked in the response body rather than throwing 5xx errors. This prevents retry storms from Microsoft Graph and maintains webhook subscription health, while still providing visibility through error logs and structured error responses.

Learnt from: vijayraghav-io
PR: #21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like @@unique([outlookSubscriptionId, eventTypeId]) should not be added as they would break this subscription sharing functionality.

🧬 Code Graph Analysis (1)
packages/features/webhooks/lib/scheduleTrigger.ts (1)
apps/api/v2/src/lib/logger.bridge.ts (1)
  • error (77-79)
🪛 GitHub Actions: PR Update
packages/trpc/server/routers/viewer/slots/reserveSlot.handler.test.ts

[error] TRPCError: Event type not found during reserveSlotHandler cookie settings tests.

packages/trpc/server/routers/viewer/slots/reserveSlot.handler.ts

[error] 151-151: TRPCError: Event type not found during 'reserveSlotHandler' step.

🔇 Additional comments (40)
apps/web/public/static/locales/bg/common.json (1)

3334-3334: New locale key added correctly
The "reservation_expired" entry is syntactically valid and the Bulgarian translation reads naturally. No further adjustments needed.

apps/web/public/static/locales/fi/common.json (1)

3334-3334: LGTM – new translation string is correct

The Finnish translation “Varaus vanhentunut” accurately reflects “reservation expired” and the JSON syntax is valid (comma-separated, quoted key/value).
No further action needed.

apps/web/public/static/locales/pl/common.json (1)

3334-3334: New key looks good – verify cross-locale consistency

The Polish translation for the newly-added key reservation_expired is clear and correct.
Please make sure the same key exists in every other locale file so runtime look-ups won’t fall back to the default language.

apps/web/public/static/locales/zh-CN/common.json (1)

3334-3334: Translation entry looks correct & consistent
Key "reservation_expired" is newly added and the Chinese value “预订已过期” accurately conveys “reservation expired”. No further action needed.

apps/web/public/static/locales/hu/common.json (1)

3334-3334: Translation looks correct – no further action needed.

The added key "reservation_expired" is correctly translated to Hungarian (“A foglalás lejárt”) and follows the existing JSON style (quotes, comma). LGTM.

apps/web/public/static/locales/no/common.json (1)

3334-3334: Adds missing Norwegian translation for reservation_expired – looks good.

apps/web/public/static/locales/en/common.json (1)

3358-3360: Looks good – remember to propagate to non-English locales
The new key/value pair is well-formed and follows existing naming conventions. Just double-check that every non-English JSON file contains the corresponding "reservation_expired" translation before merging, otherwise t() look-ups will silently fall back to the English string.

packages/prisma/schema.prisma (1)

968-988: Adding an enum value needs an irreversible Postgres migration – double-check the migration & rollback strategy

RESERVATION_EXPIRED is appended to WebhookTriggerEvents, which means Prisma will generate ALTER TYPE "WebhookTriggerEvents" ADD VALUE 'RESERVATION_EXPIRED';.
On Postgres this statement:

  1. Is irreversible (you can’t DROP VALUE), so a down-migration will silently be a no-op unless you recreate the type.
  2. Locks the enum for the duration of the change; on large tables this can briefly block writes.

Please confirm that:
• The generated migration exists and succeeds on a prod-sized DB.
• You’re comfortable that rollbacks will recreate the enum/type rather than rely on prisma migrate dev reset.
• All TypeScript/GraphQL unions derived from WebhookTriggerEvents were re-generated (prisma generate, zod, Kysely enums, etc.) so the new value is type-safe across the codebase.

If needed, create a companion “downgrade” script that recreates the enum without the new value and rewires the columns, or document that rollback is unsupported.

apps/web/public/static/locales/de/common.json (1)

3334-3334: Key added successfully – no issues found

The new translation entry for “reservation_expired” is syntactically correct (valid JSON, includes trailing comma) and follows the established key/value pattern.
No further action needed here.

apps/web/public/static/locales/sr/common.json (1)

3334-3334: New locale key looks good

Key is unique, follows existing naming convention, and translation is concise without trailing punctuation (consistent with nearby entries).
No further action needed.

apps/web/public/static/locales/ja/common.json (1)

3334-3334: Translation looks accurate – no issues found

Key reservation_expired is added with the translation 予約期限切れ, which correctly conveys “reservation expired.”
No duplication or JSON-syntax problems detected. 👍

apps/web/public/static/locales/it/common.json (1)

3334-3334: Italian translation looks good – remember to sync other locale files

"reservation_expired": "Prenotazione scaduta" is clear and idiomatic.
Confirm the same key exists in every other common.json locale to prevent undefined-string fallbacks at runtime.

apps/web/public/static/locales/da/common.json (1)

3334-3334: Localization key looks good

Key/value pair is syntactically correct, Danish translation is clear, and trailing comma keeps JSON valid. No further action needed.

apps/web/public/static/locales/es/common.json (1)

3334-3334: Localization entry looks good

Key is consistent with other locales, string reads naturally in Spanish, and surrounding commas keep the JSON valid. No further action needed.

apps/web/public/static/locales/el/common.json (1)

3334-3334: LGTM – accurate translation & valid JSON

The new reservation_expired key is syntactically correct, follows existing style (“Η κράτηση …”), and is placed in the designated “add-above” area, preserving merge-conflict guard lines.
No issues detected.

apps/web/public/static/locales/vi/common.json (1)

3333-3335: LGTM – translation key added correctly

Key reservation_expired is added with the correct Vietnamese translation and JSON syntax (including trailing comma). No other issues spotted.

apps/web/public/static/locales/et/common.json (1)

3334-3334: Translation key looks correct

The new reservation_expired key is added with an accurate Estonian translation and valid JSON syntax. No further action required.

apps/web/public/static/locales/uk/common.json (1)

3334-3334: Key added correctly; verify cross-locale coverage.

The new "reservation_expired" entry looks good linguistically ("Бронювання закінчилося"), follows the existing pattern, and contains no interpolation placeholders that would require braces.

Just double-check that the same key now exists in all locale files so that runtime look-ups never fall back to the default language.

packages/prisma/migrations/20250723210656_remove_selected_slots_realtion_with_webhook_triggers/migration.sql (1)

1-6: Confirm safe removal of selectedSlotId – irreversible destructive migration

I ran

rg -n --no-heading 'selectedSlotId'

and only found its addition and removal in migration files:

• 20250623204508_add_reservation_expired_webhook/migration.sql – adds selectedSlotId
• 20250723210656_remove_selected_slots_realtion_with_webhook_triggers/migration.sql – drops the FK and column

No references remain in application code.

Please verify:

  • Business logic or analytics don’t rely on this column anywhere (including ad-hoc queries or dashboards).
  • You have an export/archival plan for existing selectedSlotId data if it’s needed for historic replay or reporting.
apps/web/public/static/locales/nl/common.json (1)

3334-3334: Translation entry looks good.

Key reservation_expired is new, translation is idiomatic (“Reservering verlopen”) and JSON syntax remains valid. No duplication detected.

apps/web/public/static/locales/ko/common.json (1)

3334-3334: reservation_expired 번역이 추가되었습니다 – 다른 언어 리소스도 같이 업데이트됐는지 확인해주세요.

Korean 번역 자체는 자연스럽습니다. 다만 새 키를 추가할 때는 전체 locale 세트(예: en, de, fr, …)에 동일한 키가 빠짐없이 들어갔는지 한 번 더 점검해 주세요.
누락되면 런타임에 fallback 문제가 발생하거나 i18n-lint가 실패할 수 있습니다.

apps/web/public/static/locales/zh-TW/common.json (1)

3334-3334: String addition looks good – please ensure parity across locales.

"reservation_expired": "預訂已過期" is correctly translated and formatted.
Just make sure the same key exists in every other locale file so the UI doesn’t fall back to the default language.

apps/web/public/static/locales/cs/common.json (1)

3334-3334: New string looks correct

The added translation for reservation_expired (“Platnost rezervace vypršela”) is accurate Czech and the key follows the existing naming style. JSON syntax is valid (comma-separated list).

apps/web/public/static/locales/sk-SK/common.json (1)

3334-3334: Verify presence of reservation_expired across all locales

The new key is correctly added here, but please ensure:

  1. The same reservation_expired entry exists in the base (locale-neutral / en-US) file, otherwise fallback strings will break.
  2. Other production locales are updated (or at least intentionally left to fall back) so runtime look-ups don’t 404.

No action needed in this file if that’s already covered.

apps/web/public/static/locales/sk/common.json (1)

69-70: JSON fix & new key look good

• Added missing comma keeps the file valid JSON.
"reservation_expired" key follows existing naming convention and the Slovak translation “Rezervácia vypršala” is correct.

No further action needed. 👍

apps/web/public/static/locales/ar/common.json (1)

3334-3334: Consistency with existing localisation style

Key name, punctuation and Arabic translation look good and match the pattern used elsewhere (straight key / value pair, ending with a comma). No further action needed 👍

apps/web/public/static/locales/lv/common.json (1)

164-165: Translation looks good – please get it signed-off by a native speaker

The new keys are syntactically correct and you fixed the missing comma issue.
For quality assurance, have a Latvian translator quickly verify that both the grammar and tone match the rest of the file.

apps/web/public/static/locales/ta/common.json (1)

213-214: Tamil entry added correctly – double-check the wording

JSON remains valid and the key order is preserved.
Kindly ask a native Tamil reviewer to confirm that “முன்பதிவு காலாவதியானது” is the preferred phrasing in this context.

docs/developing/guides/automation/webhooks.mdx (1)

185-185: Table row correctly updated – thanks for keeping it in sync

apps/web/public/static/locales/km/common.json (1)

3334-3334: New locale key added; ensure parity across all language files

The new string "reservation_expired" is present in the Khmer locale.
Please confirm that the same key exists (with appropriate translations) in every other locale JSON under static/locales/ so translation look-ups don’t fall back to English.

If the other locale files were updated in a separate commit, you can ignore this note.

apps/web/public/static/locales/pt/common.json (1)

3334-3334: Consistent translation – looks good.

The Portuguese string follows the same pattern used elsewhere (e.g., “Reserva cancelada”) and reads naturally.
No action required.

packages/features/webhooks/lib/constants.ts (1)

23-23: Addition of RESERVATION_EXPIRED event looks correct
Enum value is properly appended and keeps the grouping consistent with the other core events.

apps/web/public/static/locales/tr/common.json (1)

3334-3334: New localization entry looks good
The key reservation_expired is properly added with an accurate Turkish translation and follows the existing formatting conventions.

apps/web/public/static/locales/hr/common.json (1)

455-456: String added correctly – no action required
The new reservation_expired key is additive, keeps the JSON valid (comma placement is correct), and follows the established naming / translation conventions.

packages/prisma/migrations/20250623204508_add_reservation_expired_webhook/migration.sql (1)

1-2: Enum value addition looks fine
Adding RESERVATION_EXPIRED is forward-only and doesn’t break existing rows.

packages/trpc/server/routers/viewer/slots/reserveSlot.handler.test.ts (2)

21-28: LGTM! Webhook mocks are properly isolated.

The mocks for getWebhooks and scheduleReservationExpiredTrigger appropriately isolate the test from external webhook dependencies, allowing the cookie settings tests to focus on their core functionality.


34-48: Mocks in reserveSlot.handler.test.ts are correctly configured—no changes needed.

The buildContext stub consistently provides a non-null eventType.findUnique return value (including teamId and team.parentId), and there are no competing mocks or resets in this file. The “Event type not found” error must be coming from a different test suite.

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

6-14: LGTM! Imports are well-organized for webhook functionality.

The new imports properly support the reservation expiration webhook feature by bringing in webhook scheduling utilities, organization/team helpers, and the necessary enum values.


37-50: LGTM! Query expansion supports webhook organization filtering.

The additional fields (teamId and team.parentId) are necessary for determining the effective team context when scheduling webhooks, especially for organization-level webhook subscriptions.

packages/features/webhooks/lib/scheduleTrigger.ts (1)

20-29: LGTM! Well-structured type definition.

The SLOT_TYPE properly defines all necessary fields for slot reservation tracking in webhook payloads.

Comment on lines +3334 to +3337
<<<<<<< HEAD
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Afegiu les vostres noves cadenes a dalt ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"reservation_expired": "Reserva caducada"
=======
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

Resolve merge-conflict markers – file is unparsable JSON

<<<<<<< HEAD, =======, and >>>>>>> … markers are still in the file together with a duplicated "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS" key.
Until these are removed the JSON cannot be parsed, which will break every build step that tries to load the locale files.

-<<<<<<< HEAD
-  "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Afegiu les vostres noves cadenes a dalt ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
-  "reservation_expired": "Reserva caducada"
-=======
+  "reservation_expired": "Reserva caducada",

After selecting the correct block:

  1. Delete all conflict markers.
  2. Keep a single copy of the sentinel key (ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS) at the very end of the object.
  3. Re-run npm run lint:locales (or equivalent) to ensure the JSON is valid.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/web/public/static/locales/ca/common.json around lines 3334 to 3337,
there are unresolved merge conflict markers including <<<<<<< HEAD and =======,
along with duplicated keys. Remove all conflict markers completely, keep only
one instance of the "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS"
key at the end of the JSON object, and then run the locale linter (e.g., npm run
lint:locales) to verify the JSON is valid and parsable.

Comment on lines 3333 to 3335
"no_members_affected_by_disabling_delegation_credential": "Ningún miembro afectado por la desactivación de credenciales de delegación",
"reservation_expired": "Reserva vencida",
"download_expense_log": "Descargar registro de gastos",
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

Duplicate key breaks the JSON payload

"download_expense_log" already exists earlier in the file.
Having the same key twice is invalid JSON and many loaders will either reject the file or silently drop the first occurrence, causing hard-to-trace i18n bugs at runtime.

   "reservation_expired": "Reserva vencida",
-  "download_expense_log": "Descargar registro de gastos",

Remove the second copy (shown above) or rename it so every key is unique.

🤖 Prompt for AI Agents
In apps/web/public/static/locales/es-419/common.json around lines 3333 to 3335,
there is a duplicate key "download_expense_log" which breaks the JSON structure.
To fix this, remove the second occurrence of the "download_expense_log" key or
rename it to a unique key to ensure all keys in the JSON file are distinct and
valid.

Comment on lines 3333 to 3335
"no_members_affected_by_disabling_delegation_credential": "Nenhum membro afetado pela desativação da credencial de delegação",
"reservation_expired": "Reserva expirada",
"download_expense_log": "Baixar registro de despesas",
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

Duplicate key breaks JSON semantics – remove the 2nd "download_expense_log" entry

The key download_expense_log appears twice (lines 3333 & 3335).
Although some JSON parsers keep the last occurrence, duplicated keys are illegal JSON and will fail strict validators / tooling (e.g. i18n extractors, TS-type generation).

  "download_expense_log": "Baixar registro de despesas",
- "reservation_expired": "Reserva expirada",
- "download_expense_log": "Baixar registro de despesas",
+ "reservation_expired": "Reserva expirada",

After the removal, the newly-added reservation_expired string is kept and the JSON stays valid.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"no_members_affected_by_disabling_delegation_credential": "Nenhum membro afetado pela desativação da credencial de delegação",
"reservation_expired": "Reserva expirada",
"download_expense_log": "Baixar registro de despesas",
"no_members_affected_by_disabling_delegation_credential": "Nenhum membro afetado pela desativação da credencial de delegação",
"download_expense_log": "Baixar registro de despesas",
"reservation_expired": "Reserva expirada",
🤖 Prompt for AI Agents
In apps/web/public/static/locales/pt-BR/common.json around lines 3333 to 3335,
there is a duplicate key "download_expense_log" which breaks JSON semantics.
Remove the second occurrence of the "download_expense_log" key to ensure the
JSON remains valid and keep the "reservation_expired" entry intact.

Comment on lines +5 to +8
ALTER TABLE "WebhookScheduledTriggers" ADD COLUMN "selectedSlotId" INTEGER;

-- AddForeignKey
ALTER TABLE "WebhookScheduledTriggers" ADD CONSTRAINT "WebhookScheduledTriggers_selectedSlotId_fkey" FOREIGN KEY ("selectedSlotId") REFERENCES "SelectedSlots"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Avoid temporary column churn – squash this change or keep the column
selectedSlotId is introduced here and removed again in a later migration in the same PR. Shipping both migrations will:

  1. Lock & rewrite the large WebhookScheduledTriggers table twice.
  2. Require two deploys/rollbacks instead of one.

Unless you actually need selectedSlotId long-term, drop the addition now and fold the enum change into a single migration:

-ALTER TABLE "WebhookScheduledTriggers" ADD COLUMN     "selectedSlotId" INTEGER;
-
--- AddForeignKey
-ALTER TABLE "WebhookScheduledTriggers" ADD CONSTRAINT "WebhookScheduledTriggers_selectedSlotId_fkey" FOREIGN KEY ("selectedSlotId") REFERENCES "SelectedSlots"("id") ON DELETE CASCADE ON UPDATE CASCADE;

Otherwise, remove the follow-up migration that deletes the column.


🏁 Script executed:

#!/bin/bash
rg "selectedSlotId" -n packages/prisma/migrations

Length of output: 1153


Eliminate temporary column churn by consolidating these migrations
You currently add then immediately drop selectedSlotId in two separate migrations:

  • packages/prisma/migrations/20250623204508_add_reservation_expired_webhook/migration.sql (adds column + FK)
  • packages/prisma/migrations/20250723210656_remove_selected_slots_realtion_with_webhook_triggers/migration.sql (drops FK + column)

Shipping both will:

  • Lock & rewrite the large WebhookScheduledTriggers table twice
  • Force two deploys/rollbacks instead of one

Choose one of the following fixes:

  • If you don’t need selectedSlotId long-term, drop both the add and drop steps and fold any enum or schema changes into a single migration.
  • If you do need the column, remove the second migration (20250723210656_remove_selected_slots_realtion_with_webhook_triggers) so that the column remains in place.
🤖 Prompt for AI Agents
In
packages/prisma/migrations/20250623204508_add_reservation_expired_webhook/migration.sql
lines 5 to 8, you add the selectedSlotId column and foreign key but then
immediately drop them in a later migration, causing unnecessary table locks and
rewrites. To fix this, either remove both the add and drop steps and consolidate
any related schema changes into a single migration if the column is not needed
long-term, or if the column is needed, delete the later migration that drops the
column and foreign key to keep the column intact.

Comment on lines 105 to 107
// FIXME: In case of team event, users doesn't have assignees, those are in hosts. users just have the creator of the event which is wrong.
// Also, we must not block all the users' slots, we must use routedTeamMemberIds if set like we do in getSchedule.
// We could even improve it by identifying the next person being booked now that we have a queue of assignees.
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

Address the FIXME comment about team event assignees.

The comment indicates that for team events, the users array might contain only the event creator rather than the actual assignees. This could lead to incorrect slot reservations and webhook scheduling.

Would you like me to help implement the proper logic for handling team event assignees using routedTeamMemberIds as mentioned in the comment?

🤖 Prompt for AI Agents
In packages/trpc/server/routers/viewer/slots/reserveSlot.handler.ts around lines
105 to 107, the current logic incorrectly uses the event creator as the assignee
for team events, which causes wrong slot reservations. Update the code to check
if routedTeamMemberIds is set and use those IDs as the actual assignees instead
of the users array. This will ensure only the relevant team members' slots are
blocked and webhook scheduling is accurate. Adjust the logic to handle the queue
of assignees if applicable, similar to the approach in getSchedule.

Copy link
Contributor

@kart1ka kart1ka left a comment

Choose a reason for hiding this comment

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

There are lots of unrelated file changes in this PR. Can you clean things up a bit and keep only the changes related to the issue at hand?
There also seems to be a test failing. Pls fix that.
I can see there are two migration files which seems to be bit messy. can you clean those up as well?

@kart1ka kart1ka marked this pull request as draft July 24, 2025 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api area: API, enterprise API, access token, OAuth ✨ feature New feature or request i18n area: i18n, translations ❗️ migrations contains migration files platform Anything related to our platform plan webhooks area: webhooks, callback, webhook payload
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feature: expired reservation tracking
2 participants