Skip to content

Comments

fix: phone number billing bug#23851

Merged
emrysal merged 6 commits intomainfrom
fix/billing-phone
Sep 15, 2025
Merged

fix: phone number billing bug#23851
emrysal merged 6 commits intomainfrom
fix/billing-phone

Conversation

@Udit-takkar
Copy link
Contributor

@Udit-takkar Udit-takkar commented Sep 15, 2025

What does this PR do?

Don't delete from stripe if it doesn't exist

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • N/A 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?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 15, 2025

Walkthrough

The cancelPhoneNumberSubscription flow in packages/features/calAIPhone/providers/retellAI/services/BillingService.ts now imports zod and defines a stripeResourceMissingErrorSchema. The Stripe cancellation call is wrapped in a nested try-catch: errors matching type invalid_request_error and code resource_missing are logged (including subscriptionId and phoneNumberId) and treated as non-fatal, while other Stripe errors are rethrown. DB update, Retell deletion, and remaining error handling are unchanged. Tests in the corresponding tests file add cases for Stripe returning resource_missing (treated as success) and for non-resource_missing Stripe failures (operation rejects; no DB update). No public/exported signatures changed.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title "fix: phone number billing bug" correctly identifies the change as a bug fix related to phone number billing and aligns with the BillingService change that tolerates Stripe resource_missing errors during subscription cancellation; it is a concise, single-sentence summary and not misleading. Although a bit generic, it still meaningfully reflects the primary intent of the changeset.
Description Check ✅ Passed The PR description states "Don't delete from stripe if it doesn't exist" and includes the mandatory checklist, which directly matches the implemented change to handle Stripe resource_missing errors and the added tests; therefore the description is related to the changeset and passes this lenient check. The description is brief but on-topic.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/billing-phone

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

@graphite-app graphite-app bot requested a review from a team September 15, 2025 14:33
@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Sep 15, 2025
@dosubot dosubot bot added billing area: billing, stripe, payments, paypal, get paid 🐛 bug Something isn't working labels Sep 15, 2025
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: 0

🧹 Nitpick comments (5)
packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (1)

142-151: Tighten error typing and add idempotency key to the Stripe cancel call.

  • Use unknown + a small type guard to avoid any in the catch and make the code check robust.
  • Add an idempotencyKey to the cancel request to protect against network retries or concurrent attempts.
-      } catch (error: any) {
-        if (error.code === 'resource_missing') {
+      } catch (error: unknown) {
+        const code =
+          typeof error === "object" && error !== null && "code" in error
+            ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
+              (error as any).code
+            : undefined;
+        if (code === "resource_missing") {
           needsStripeCancellation = false;
           this.logger.warn("Subscription not found in Stripe:", {
             subscriptionId: phoneNumber.stripeSubscriptionId,
             phoneNumberId,
           });
         } else {
           throw error;
         }
       }
 
       if (needsStripeCancellation) {
-        await stripe.subscriptions.cancel(phoneNumber.stripeSubscriptionId);
+        await stripe.subscriptions.cancel(
+          phoneNumber.stripeSubscriptionId,
+          undefined,
+          { idempotencyKey: `cancel:${phoneNumber.stripeSubscriptionId}` }
+        );
       }

Also applies to: 154-156

packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts (4)

25-26: Remove duplicate default mock for subscriptions.retrieve.

retrieve is mocked both in the module factory and again in beforeEach. Keep one (prefer beforeEach) to avoid confusing test setup.

 vi.mock("@calcom/features/ee/payments/server/stripe", () => ({
   default: {
     checkout: {
       sessions: {
         create: vi.fn().mockResolvedValue({
           url: "https://checkout.stripe.com/session-123",
         }),
       },
     },
     subscriptions: {
       cancel: vi.fn().mockResolvedValue({}),
-      retrieve: vi.fn().mockResolvedValue({ status: "active" }),
     },
   },
 }));
 
 // ...
 beforeEach(async () => {
   vi.clearAllMocks();
   mocks = setupBasicMocks();
 
   const stripe = (await import("@calcom/features/ee/payments/server/stripe")).default;
   stripe.checkout.sessions.create.mockResolvedValue({
     url: "https://checkout.stripe.com/session-123",
   });
   stripe.subscriptions.cancel.mockResolvedValue({});
   stripe.subscriptions.retrieve.mockResolvedValue({ status: "active" });

Also applies to: 51-52


260-291: Assert Retell deletion also runs in “already canceled in Stripe” path.

The service still deletes the phone number from Retell on idempotent paths. Add an assertion to guard this behavior.

       expect(mocks.mockPhoneNumberRepository.updateSubscriptionStatus).toHaveBeenCalledWith({
         id: 1,
         subscriptionStatus: PhoneNumberSubscriptionStatus.CANCELLED,
         disconnectOutboundAgent: true,
       });
+      expect(mocks.mockRetellRepository.deletePhoneNumber).toHaveBeenCalledWith("+1234567890");

293-324: Also assert Retell deletion when Stripe returns resource_missing.

Strengthens coverage of the idempotent “not found” path.

       expect(mocks.mockPhoneNumberRepository.updateSubscriptionStatus).toHaveBeenCalledWith({
         id: 1,
         subscriptionStatus: PhoneNumberSubscriptionStatus.CANCELLED,
         disconnectOutboundAgent: true,
       });
+      expect(mocks.mockRetellRepository.deletePhoneNumber).toHaveBeenCalledWith("+1234567890");

326-348: Ensure Retell deletion is not attempted on retrieve failure.

On non-resource_missing retrieve errors, the service throws before DB/Retell effects. Assert Retell delete wasn’t called.

       // Should NOT attempt to cancel due to error
       expect(stripe.subscriptions.cancel).not.toHaveBeenCalled();
       // Should NOT update database due to error
       expect(mocks.mockPhoneNumberRepository.updateSubscriptionStatus).not.toHaveBeenCalled();
+      // Should NOT attempt Retell deletion
+      expect(mocks.mockRetellRepository.deletePhoneNumber).not.toHaveBeenCalled();
📜 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 41553f6 and 10928a1.

📒 Files selected for processing (2)
  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (1 hunks)
  • packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*Service.ts

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

Service files must include Service suffix, use PascalCase matching exported class, and avoid generic names (e.g., MembershipService.ts)

Files:

  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts
**/*.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/features/calAIPhone/providers/retellAI/services/BillingService.ts
  • packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.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/features/calAIPhone/providers/retellAI/services/BillingService.ts
  • packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.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/features/calAIPhone/providers/retellAI/services/BillingService.ts
  • packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts:13-24
Timestamp: 2025-08-21T16:34:10.839Z
Learning: In calcom/cal.com PR #22995, the deletePhoneNumber function in packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts is only used for imported phone numbers that don't have active Stripe subscriptions. Purchased phone numbers with subscriptions use a separate cancellation flow first (per maintainer Udit-takkar).
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).
📚 Learning: 2025-08-08T10:26:13.362Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).

Applied to files:

  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts
📚 Learning: 2025-08-21T16:34:10.839Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts:13-24
Timestamp: 2025-08-21T16:34:10.839Z
Learning: In calcom/cal.com PR #22995, the deletePhoneNumber function in packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts is only used for imported phone numbers that don't have active Stripe subscriptions. Purchased phone numbers with subscriptions use a separate cancellation flow first (per maintainer Udit-takkar).

Applied to files:

  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts
🧬 Code graph analysis (2)
packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (2)
packages/app-store/_utils/stripe.ts (1)
  • stripe (70-72)
apps/api/v2/src/lib/logger.bridge.ts (1)
  • error (77-79)
packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts (1)
packages/features/calAIPhone/providers/retellAI/services/__tests__/test-utils.ts (2)
  • createMockPhoneNumberRecord (66-79)
  • TestError (194-199)
⏰ 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). (4)
  • GitHub Check: Tests / Unit
  • GitHub Check: Linters / lint
  • GitHub Check: Type check / check-types
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (1)
packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (1)

132-156: Good guard: prevent redundant/erroneous Stripe cancellation.

Pre-retrieving the subscription and skipping cancel on "canceled" or "resource_missing" aligns with the PR goal and makes the flow idempotent-enough for common retries.

Please confirm Stripe errors surface code: "resource_missing" from the wrapper at @calcom/features/ee/payments/server/stripe in your env (API version 2020-08-27 snippet suggests yes). If that wrapper normalizes errors differently, we should adjust the check.

@pull-request-size pull-request-size bot added size/M and removed size/L labels Sep 15, 2025
@vercel
Copy link

vercel bot commented Sep 15, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Sep 15, 2025 3:38pm
cal-eu Ignored Ignored Sep 15, 2025 3:38pm

await stripe.subscriptions.cancel(phoneNumber.stripeSubscriptionId);
try {
await stripe.subscriptions.cancel(phoneNumber.stripeSubscriptionId);
} catch (error: any) {
Copy link
Contributor

Choose a reason for hiding this comment

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

} catch (error: unknown) {
  if (error instanceof Error && error.code === "resource_missing" /* ideally this is a enum of sorts? */) {
   ..

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

♻️ Duplicate comments (1)
packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (1)

143-157: Use a resilient guard for Stripe “resource_missing”; log useful fields

Replace the zod-parse branch with a simple predicate that checks code (and raw.code). Also surface request_log_url when present to speed up Stripe dashboard triage.

-      try {
-        await stripe.subscriptions.cancel(phoneNumber.stripeSubscriptionId);
-      } catch (error) {
-        const parsedError = stripeResourceMissingErrorSchema.safeParse(error);
-
-        if (parsedError.success) {
-          this.logger.info("Subscription not found in Stripe (already cancelled or deleted):", {
-            subscriptionId: phoneNumber.stripeSubscriptionId,
-            phoneNumberId,
-            stripeMessage: parsedError.data.message,
-          });
-        } else {
-          throw error;
-        }
-      }
+      try {
+        await stripe.subscriptions.cancel(phoneNumber.stripeSubscriptionId);
+      } catch (error) {
+        if (isResourceMissingStripeError(error)) {
+          const err: any = error;
+          this.logger.info("Subscription not found in Stripe (already cancelled or deleted):", {
+            subscriptionId: phoneNumber.stripeSubscriptionId,
+            phoneNumberId,
+            stripeMessage: err?.message,
+            stripeRequestLogUrl: err?.request_log_url ?? err?.raw?.request_log_url,
+          });
+        } else {
+          throw error;
+        }
+      }

Also consider hoisting "resource_missing" into a central enum/const to avoid stringly‑typed checks across the codebase.

🧹 Nitpick comments (1)
packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (1)

1-1: Avoid pulling zod for single error-shape check

If the above guard is adopted, drop the zod import to keep the service lean.

📜 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 a815615 and ab210df.

📒 Files selected for processing (1)
  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*Service.ts

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

Service files must include Service suffix, use PascalCase matching exported class, and avoid generic names (e.g., MembershipService.ts)

Files:

  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts
**/*.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/features/calAIPhone/providers/retellAI/services/BillingService.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/features/calAIPhone/providers/retellAI/services/BillingService.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/features/calAIPhone/providers/retellAI/services/BillingService.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts:13-24
Timestamp: 2025-08-21T16:34:10.839Z
Learning: In calcom/cal.com PR #22995, the deletePhoneNumber function in packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts is only used for imported phone numbers that don't have active Stripe subscriptions. Purchased phone numbers with subscriptions use a separate cancellation flow first (per maintainer Udit-takkar).
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.
📚 Learning: 2025-08-08T10:26:13.362Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).

Applied to files:

  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts
📚 Learning: 2025-08-21T16:34:10.839Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts:13-24
Timestamp: 2025-08-21T16:34:10.839Z
Learning: In calcom/cal.com PR #22995, the deletePhoneNumber function in packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts is only used for imported phone numbers that don't have active Stripe subscriptions. Purchased phone numbers with subscriptions use a separate cancellation flow first (per maintainer Udit-takkar).

Applied to files:

  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts
🧬 Code graph analysis (1)
packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (1)
packages/app-store/_utils/stripe.ts (1)
  • stripe (70-72)

Copy link
Contributor

@emrysal emrysal left a comment

Choose a reason for hiding this comment

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

Looks good to me, significantly better handling than before and should fix 500 error.

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: 0

🧹 Nitpick comments (2)
packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts (2)

257-293: Also assert Retell deletion on Stripe 404 path.

We’re treating Stripe resource_missing as success; the test should verify we still delete the Retell phone number. Add an assertion to prevent regressions.

Apply this diff:

       expect(mocks.mockPhoneNumberRepository.updateSubscriptionStatus).toHaveBeenCalledWith({
         id: 1,
         subscriptionStatus: PhoneNumberSubscriptionStatus.CANCELLED,
         disconnectOutboundAgent: true,
       });
+      expect(mocks.mockRetellRepository.deletePhoneNumber).toHaveBeenCalledWith("+1234567890");

Nit: include optional request_log_url in the mocked error for future‑proofing.

Schema allows it; adding reduces brittleness if validation tightens later.

       stripe.subscriptions.cancel.mockRejectedValue({
         type: "invalid_request_error",
         code: "resource_missing",
         message: "No such subscription: 'sub_123'",
         param: "id",
         doc_url: "https://stripe.com/docs/error-codes/resource-missing",
+        request_log_url: "https://dashboard.stripe.com/test/logs/req_123",
       });

295-315: Assert Retell deletion is not attempted on non‑resource_missing failures.

We already assert no DB update; also guard that Retell deletion isn’t called when cancellation fails.

Apply this diff:

       await expect(service.cancelPhoneNumberSubscription(validCancelData)).rejects.toThrow(
         "Failed to cancel subscription"
       );

       // Should attempt to cancel
       expect(stripe.subscriptions.cancel).toHaveBeenCalledWith("sub_123");
       // Should NOT update database due to error
       expect(mocks.mockPhoneNumberRepository.updateSubscriptionStatus).not.toHaveBeenCalled();
+      // Should NOT delete Retell number on failure
+      expect(mocks.mockRetellRepository.deletePhoneNumber).not.toHaveBeenCalled();
📜 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 ab210df and e3dc687.

📒 Files selected for processing (2)
  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts (3 hunks)
  • packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/features/calAIPhone/providers/retellAI/services/BillingService.ts
🧰 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/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.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/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.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/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts:13-24
Timestamp: 2025-08-21T16:34:10.839Z
Learning: In calcom/cal.com PR #22995, the deletePhoneNumber function in packages/trpc/server/routers/viewer/phoneNumber/delete.handler.ts is only used for imported phone numbers that don't have active Stripe subscriptions. Purchased phone numbers with subscriptions use a separate cancellation flow first (per maintainer Udit-takkar).
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.
🧬 Code graph analysis (1)
packages/features/calAIPhone/providers/retellAI/services/__tests__/BillingService.test.ts (1)
packages/features/calAIPhone/providers/retellAI/services/__tests__/test-utils.ts (2)
  • createMockPhoneNumberRecord (66-79)
  • TestError (194-199)

@github-actions
Copy link
Contributor

E2E results are ready!

@emrysal emrysal merged commit 0c2ba81 into main Sep 15, 2025
62 of 64 checks passed
@emrysal emrysal deleted the fix/billing-phone branch September 15, 2025 16:17
@coderabbitai coderabbitai bot mentioned this pull request Sep 16, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

billing area: billing, stripe, payments, paypal, get paid 🐛 bug Something isn't working core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ready-for-e2e size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants