Skip to content

Conversation

joeauyeung
Copy link
Contributor

@joeauyeung joeauyeung commented Oct 10, 2025

What does this PR do?

  • Adds subscriptionStart, subscriptionTrialEnd and subscriptionEnd fields to the TeamBilling and OrganizationBilling tables.
  • Writes subscriptionStart dates when new organizations and teams are created
  • Fixes a type in the stripe-billing-service file (billling -> billing)

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?

  • Create a new team & org and checkout
    • The subscription start date should be written to the billing table

@github-actions github-actions bot added the ❗️ migrations contains migration files label Oct 10, 2025
@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Oct 10, 2025
Copy link
Contributor

coderabbitai bot commented Oct 10, 2025

Walkthrough

Adds subscription date fields across billing: Prisma schema and a migration add subscriptionStart, subscriptionTrialEnd, and subscriptionEnd to TeamBilling and OrganizationBilling. IBillingRepositoryCreateArgs gains optional Date fields for subscriptionStart, subscriptionTrialEnd, and subscriptionEnd and SubscriptionStatus gains new members (INCOMPLETE, INCOMPLETE_EXPIRED, UNPAID, PAUSED). StripeBillingService adds static extractSubscriptionDates (converts Stripe epoch-second fields to JS Dates) and a Stripe->internal status mapper. Routes and webhook handlers call extractSubscriptionDates and pass subscriptionStart into InternalTeamBilling.saveTeamBilling. Multiple import-path typos for StripeBillingService were corrected. EventType public unique constraints removed.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately describes the primary change of adding subscription start, trial end, and end dates to the billing tables and aligns with the main modification in the pull request.
Description Check ✅ Passed The description directly relates to the changeset by outlining the added subscriptionStart, subscriptionTrialEnd, and subscriptionEnd fields in the TeamBilling and OrganizationBilling tables, notes the typo fix in the billing service, and includes relevant testing instructions.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch billing-table-add-dates

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.

});

// Get the Stripe subscription object
const stripeSubscription = await stripe.subscriptions.retrieve(paymentSubscriptionId);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The data returned from the invoice_paid event doesn't contain the subscription info so we need to fetch that from Stripe.

Since this is happening in the background, the extra Stripe call won't affect UX.

Copy link
Contributor

github-actions bot commented Oct 10, 2025

E2E results are ready!

@joeauyeung joeauyeung marked this pull request as ready for review October 10, 2025 15:06
@joeauyeung joeauyeung requested a review from a team as a code owner October 10, 2025 15:06
@graphite-app graphite-app bot requested a review from a team October 10, 2025 15:07
@dosubot dosubot bot added the billing area: billing, stripe, payments, paypal, get paid label Oct 10, 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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/prisma/schema.prisma (1)

250-252: Remove unrelated changes to EventType unique constraints.

The removal of these three unique constraints on EventType is not mentioned in the PR objectives and appears unrelated to adding billing date fields. This change could have significant implications:

  • Allows duplicate slugs per user/team, which could break routing or cause conflicts
  • Allows duplicate parentId entries, which could create data integrity issues

If these constraint removals are intentional, they should be in a separate PR with proper justification and testing.

📜 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 eae2711 and 6dba2d1.

📒 Files selected for processing (6)
  • apps/web/app/api/teams/api/create/route.ts (1 hunks)
  • apps/web/app/api/teams/create/route.ts (1 hunks)
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (3 hunks)
  • packages/features/ee/billing/repository/IBillingRepository.ts (1 hunks)
  • packages/prisma/migrations/20251010135752_billing_tables_add_dates/migration.sql (1 hunks)
  • packages/prisma/schema.prisma (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.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:

  • apps/web/app/api/teams/api/create/route.ts
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/ee/billing/repository/IBillingRepository.ts
  • apps/web/app/api/teams/create/route.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:

  • apps/web/app/api/teams/api/create/route.ts
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/ee/billing/repository/IBillingRepository.ts
  • apps/web/app/api/teams/create/route.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:

  • apps/web/app/api/teams/api/create/route.ts
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/ee/billing/repository/IBillingRepository.ts
  • apps/web/app/api/teams/create/route.ts
**/*Repository.ts

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

Repository files must include Repository suffix, prefix with technology if applicable (e.g., PrismaAppRepository.ts), and use PascalCase matching the exported class

Files:

  • packages/features/ee/billing/repository/IBillingRepository.ts
🧬 Code graph analysis (1)
packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (1)
packages/app-store/_utils/stripe.ts (1)
  • stripe (70-72)
🔇 Additional comments (8)
apps/web/app/api/teams/api/create/route.ts (1)

69-70: LGTM!

The subscriptionStart calculation correctly converts Unix seconds to milliseconds, and the comment clearly explains the conversion.

packages/prisma/migrations/20251010135752_billing_tables_add_dates/migration.sql (1)

1-9: LGTM!

The migration correctly adds the three new date columns to both billing tables as nullable fields, which is appropriate for existing records.

packages/prisma/schema.prisma (2)

2619-2621: LGTM!

The addition of subscriptionStart, subscriptionTrialEnd, and subscriptionEnd fields to TeamBilling correctly implements the schema changes for the new billing date tracking feature.


2637-2639: LGTM!

The addition of subscriptionStart, subscriptionTrialEnd, and subscriptionEnd fields to OrganizationBilling correctly implements the schema changes for the new billing date tracking feature.

apps/web/app/api/teams/create/route.ts (1)

99-100: LGTM!

The subscriptionStart calculation is correct and consistent with the implementation in the other team creation route. The conversion from Unix seconds to milliseconds is properly explained.

packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (2)

6-6: Consider upgrading the Stripe SDK version.

Based on learnings, the current Stripe SDK version (using API version 2020-08-27 as shown in packages/app-store/_utils/stripe.ts) is significantly outdated. The Stripe Node SDK has progressed through many major versions since 3.x, with improvements including:

  • Modern TypeScript support and generated types
  • Better retry/backoff behavior
  • Support for newer Stripe API features
  • Security fixes

While not blocking for this PR, consider planning an upgrade to benefit from these improvements.

Based on learnings


100-113: LGTM!

The implementation correctly:

  • Fetches the Stripe subscription to access the created timestamp (as explained in the past review comment)
  • Converts Unix seconds to milliseconds for the Date constructor
  • Populates subscriptionStart in the billing record

The extra Stripe API call in the background webhook handler is justified and won't impact user experience.

packages/features/ee/billing/repository/IBillingRepository.ts (1)

40-42: Verify population of subscriptionTrialEnd and subscriptionEnd fields.

The interface correctly adds all three date fields, but only subscriptionStart is currently populated in the codebase. Consider whether subscriptionTrialEnd and subscriptionEnd should also be populated from Stripe data:

  • subscriptionTrialEnd: Available as subscription.trial_end in Stripe
  • subscriptionEnd: Available as subscription.ended_at or subscription.cancel_at in Stripe

If these fields are intended for future use, this is fine as they're optional. However, if they should be populated now, the webhook and route handlers should be updated accordingly.

Copy link

vercel bot commented Oct 10, 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 Oct 10, 2025 7:46pm
cal-eu Ignored Ignored Oct 10, 2025 7:46pm

Comment on lines +61 to +63
const { subscriptionStart } =
StripeBillingService.extractSubscriptionDates(checkoutSessionSubscription);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since we always have to convert Stripe's time from unix seconds to milliseconds when passing to Date(), I decided to create a static method on the StripeBillingService

});

vi.mock("@calcom/features/ee/billing/stripe-billling-service", () => {
vi.mock("@calcom/features/ee/billing/stripe-billing-service", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I noticed that the file name for the StripeBillingService had a typo so I'm fixing that in this PR.

invoice_creation: {
enabled: true,
},
// eslint-disable-next-line
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lint fix. Since the checkout session mode is "payment" the invoice_creation is a valid argument but this throws a type error.


async handleSubscriptionCreation(subscriptionId: string) {
throw new Error("Method not implemented.");
throw new Error(`Method not implemented for subscription id ${subscriptionId}`);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lint fix

return price;
}

static extractSubscriptionDates(subscription: {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Single method to convert Stripe's dates to Date object

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/features/ee/billing/stripe-billing-service.ts (1)

61-61: Clarify the purpose of the eslint-disable comment.

The eslint-disable-next-line comment lacks context about which rule is being disabled and why. Consider adding a brief explanation or the specific rule name.

Example:

-      // eslint-disable-next-line
+      // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Stripe session type doesn't match exactly
apps/web/app/api/teams/create/route.ts (2)

91-91: Consider extracting and storing all subscription date fields.

The extractSubscriptionDates method returns three fields (subscriptionStart, subscriptionTrialEnd, subscriptionEndDate), but only subscriptionStart is currently extracted and stored. Since the PR adds all three fields to the billing schema and the data is already being computed, consider destructuring and passing all three to saveTeamBilling for completeness.

Apply this diff to extract all date fields:

-    const { subscriptionStart } = StripeBillingService.extractSubscriptionDates(subscription);
+    const { subscriptionStart, subscriptionTrialEnd, subscriptionEndDate } = StripeBillingService.extractSubscriptionDates(subscription);

Then pass all three fields to saveTeamBilling:

     await internalBillingService.saveTeamBilling({
       teamId: team.id,
       subscriptionId: subscription.id,
       subscriptionItemId: subscription.items.data[0].id,
       customerId: subscription.customer as string,
       // TODO: Implement true subscription status when webhook events are implemented
       status: SubscriptionStatus.ACTIVE,
       planName: Plan.TEAM,
       // Stripe returns time in unix seconds but new Date() expects milliseconds
       subscriptionStart,
+      subscriptionTrialEnd,
+      subscriptionEnd: subscriptionEndDate,
     });

101-102: Consider updating the comment for clarity.

The comment about unix seconds and milliseconds conversion is placed here, but the actual conversion happens inside StripeBillingService.extractSubscriptionDates() at line 91. By the time subscriptionStart reaches this point, it's already a Date object. Consider updating the comment to clarify this, or remove it since the conversion is documented in the extractSubscriptionDates method.

Example clarification:

-      // Stripe returns time in unix seconds but new Date() expects milliseconds
-      subscriptionStart,
+      subscriptionStart, // Already converted from Stripe's unix seconds to Date
📜 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 6dba2d1 and 2d21a1b.

📒 Files selected for processing (16)
  • apps/web/app/api/teams/api/create/route.ts (3 hunks)
  • apps/web/app/api/teams/create/route.ts (3 hunks)
  • apps/web/lib/pages/auth/verify-email.test.ts (1 hunks)
  • apps/web/lib/pages/auth/verify-email.ts (1 hunks)
  • packages/app-store/stripepayment/lib/getCustomerAndCheckoutSession.ts (1 hunks)
  • packages/features/auth/signup/handlers/calcomHandler.ts (1 hunks)
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (3 hunks)
  • packages/features/ee/billing/credit-service.test.ts (1 hunks)
  • packages/features/ee/billing/credit-service.ts (1 hunks)
  • packages/features/ee/billing/stripe-billing-service.test.ts (1 hunks)
  • packages/features/ee/billing/stripe-billing-service.ts (3 hunks)
  • packages/features/ee/organizations/lib/OrganizationPaymentService.test.ts (1 hunks)
  • packages/features/ee/organizations/lib/OrganizationPaymentService.ts (1 hunks)
  • packages/trpc/server/routers/loggedInViewer/stripeCustomer.handler.ts (1 hunks)
  • packages/trpc/server/routers/viewer/credits/buyCredits.handler.ts (1 hunks)
  • packages/trpc/server/routers/viewer/me/updateProfile.handler.ts (1 hunks)
✅ Files skipped from review due to trivial changes (7)
  • apps/web/lib/pages/auth/verify-email.test.ts
  • packages/trpc/server/routers/loggedInViewer/stripeCustomer.handler.ts
  • packages/features/ee/billing/credit-service.ts
  • packages/features/ee/billing/credit-service.test.ts
  • packages/features/ee/organizations/lib/OrganizationPaymentService.test.ts
  • apps/web/lib/pages/auth/verify-email.ts
  • packages/trpc/server/routers/viewer/credits/buyCredits.handler.ts
🧰 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/ee/organizations/lib/OrganizationPaymentService.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/ee/organizations/lib/OrganizationPaymentService.ts
  • apps/web/app/api/teams/api/create/route.ts
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/auth/signup/handlers/calcomHandler.ts
  • packages/features/ee/billing/stripe-billing-service.ts
  • apps/web/app/api/teams/create/route.ts
  • packages/features/ee/billing/stripe-billing-service.test.ts
  • packages/trpc/server/routers/viewer/me/updateProfile.handler.ts
  • packages/app-store/stripepayment/lib/getCustomerAndCheckoutSession.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/ee/organizations/lib/OrganizationPaymentService.ts
  • apps/web/app/api/teams/api/create/route.ts
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/auth/signup/handlers/calcomHandler.ts
  • packages/features/ee/billing/stripe-billing-service.ts
  • apps/web/app/api/teams/create/route.ts
  • packages/features/ee/billing/stripe-billing-service.test.ts
  • packages/trpc/server/routers/viewer/me/updateProfile.handler.ts
  • packages/app-store/stripepayment/lib/getCustomerAndCheckoutSession.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/ee/organizations/lib/OrganizationPaymentService.ts
  • apps/web/app/api/teams/api/create/route.ts
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/auth/signup/handlers/calcomHandler.ts
  • packages/features/ee/billing/stripe-billing-service.ts
  • apps/web/app/api/teams/create/route.ts
  • packages/features/ee/billing/stripe-billing-service.test.ts
  • packages/trpc/server/routers/viewer/me/updateProfile.handler.ts
  • packages/app-store/stripepayment/lib/getCustomerAndCheckoutSession.ts
🧬 Code graph analysis (3)
apps/web/app/api/teams/api/create/route.ts (1)
packages/features/ee/billing/stripe-billing-service.ts (1)
  • StripeBillingService (5-213)
packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (2)
packages/app-store/_utils/stripe.ts (1)
  • stripe (70-72)
packages/features/ee/billing/stripe-billing-service.ts (1)
  • StripeBillingService (5-213)
apps/web/app/api/teams/create/route.ts (1)
packages/features/ee/billing/stripe-billing-service.ts (1)
  • StripeBillingService (5-213)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (11)
packages/trpc/server/routers/viewer/me/updateProfile.handler.ts (1)

7-7: LGTM!

Import path typo corrected from "stripe-billling-service" to "stripe-billing-service".

packages/features/ee/billing/stripe-billing-service.test.ts (1)

4-4: LGTM!

Import path typo corrected.

packages/app-store/stripepayment/lib/getCustomerAndCheckoutSession.ts (1)

1-1: LGTM!

Import path typo corrected.

packages/features/ee/organizations/lib/OrganizationPaymentService.ts (1)

1-1: LGTM!

Import path typo corrected.

packages/features/auth/signup/handlers/calcomHandler.ts (1)

8-8: LGTM!

Import path typo corrected.

packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (2)

4-7: LGTM!

Import path corrected and necessary Stripe client imported for subscription retrieval.


101-116: LGTM!

Correctly retrieves the Stripe subscription and extracts subscriptionStart for billing records. The additional Stripe API call is acceptable in this background webhook context.

The comment on line 114 about UNIX seconds to milliseconds conversion is slightly redundant since the conversion is already handled by extractSubscriptionDates, but it serves as helpful documentation.

apps/web/app/api/teams/api/create/route.ts (2)

8-8: LGTM!

Import added for subscription date extraction.


60-76: LGTM!

Correctly extracts subscriptionStart from the expanded Stripe subscription and passes it to the billing service. The checkout session retrieval at line 100-102 properly expands the subscription to ensure all date fields are available.

The comment on line 73 about UNIX seconds to milliseconds conversion is slightly redundant since extractSubscriptionDates handles this, but it provides helpful context.

packages/features/ee/billing/stripe-billing-service.ts (1)

131-131: LGTM!

Error message improvement provides better context by including the subscription ID.

apps/web/app/api/teams/create/route.ts (1)

8-8: LGTM!

The import is correctly added and used in the file to extract subscription dates.

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 (1)
apps/web/app/api/teams/api/create/route.ts (1)

40-58: Prefer Prisma select over include.

The Prisma query uses include: { members: true } which fetches all member fields. Per coding guidelines, you should use select to explicitly specify only the fields you need.

As per coding guidelines.

Apply this diff to use select instead of include:

 const finalizedTeam = await prisma.team.update({
   where: { id: checkoutSessionMetadata.pendingPaymentTeamId },
   data: {
     pendingPayment: false,
     members: {
       create: {
         userId: checkoutSessionMetadata.ownerId as number,
         role: MembershipRole.OWNER,
         accepted: true,
       },
     },
     metadata: {
       paymentId: checkoutSession.id,
       subscriptionId: checkoutSessionSubscription.id || null,
       subscriptionItemId: checkoutSessionSubscription.items.data[0].id || null,
     },
   },
-  include: { members: true },
+  select: {
+    id: true,
+    name: true,
+    slug: true,
+    members: {
+      select: {
+        id: true,
+        userId: true,
+        teamId: true,
+        role: true,
+        accepted: true,
+        disableImpersonation: true,
+      },
+    },
+  },
 });
📜 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 2d21a1b and 82a2e91.

📒 Files selected for processing (4)
  • apps/web/app/api/teams/api/create/route.ts (3 hunks)
  • apps/web/app/api/teams/create/route.ts (3 hunks)
  • packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (3 hunks)
  • packages/features/ee/billing/stripe-billing-service.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/api/teams/create/route.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/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/ee/billing/stripe-billing-service.ts
  • apps/web/app/api/teams/api/create/route.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/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/ee/billing/stripe-billing-service.ts
  • apps/web/app/api/teams/api/create/route.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/ee/billing/api/webhook/_invoice.paid.org.ts
  • packages/features/ee/billing/stripe-billing-service.ts
  • apps/web/app/api/teams/api/create/route.ts
🧬 Code graph analysis (2)
packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (2)
packages/app-store/_utils/stripe.ts (1)
  • stripe (70-72)
packages/features/ee/billing/stripe-billing-service.ts (1)
  • StripeBillingService (5-213)
apps/web/app/api/teams/api/create/route.ts (1)
packages/features/ee/billing/stripe-billing-service.ts (1)
  • StripeBillingService (5-213)
🔇 Additional comments (4)
packages/features/ee/billing/stripe-billing-service.ts (2)

131-131: LGTM: Improved error message.

The error message now includes the subscription ID, providing better context for debugging.


201-212: LGTM: Subscription date conversion is correct.

The static helper correctly converts Stripe's Unix timestamps (seconds) to JavaScript Date objects (milliseconds) and properly handles optional/nullable fields.

packages/features/ee/billing/api/webhook/_invoice.paid.org.ts (1)

101-114: LGTM: Subscription start date extraction is correct.

The code properly retrieves the Stripe subscription object and extracts subscriptionStart for persistence. The extra API call is acceptable in this webhook handler context since it runs in the background. The outer try-catch block (line 75) will handle any errors from the subscription retrieval.

Note: Only subscriptionStart is currently populated, which aligns with the PR scope. The schema supports subscriptionTrialEnd and subscriptionEnd as well, which could be populated in future iterations.

apps/web/app/api/teams/api/create/route.ts (1)

61-73: LGTM: Subscription start date extraction is correct.

The code properly extracts subscriptionStart from the checkout session subscription and passes it to the billing service. The formatting and logic are sound.

Note: Only subscriptionStart is currently populated, which aligns with the PR scope. The schema supports subscriptionTrialEnd and subscriptionEnd as well, which could be populated in future iterations.

@pull-request-size pull-request-size bot added size/L and removed size/M labels Oct 10, 2025
return { subscriptionStart, subscriptionTrialEnd, subscriptionEnd };
}

static mapStripeStatusToCalStatus = ({
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commit meant for #24390 but keeping it in here because it's stacked on top.

- Add INCOMPLETE, INCOMPLETE_EXPIRED, UNPAID, PAUSED enum values
- These values are referenced in stripe-billing-service.ts status mapping
- Fixes type errors in billing-related code

Co-Authored-By: [email protected] <[email protected]>
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 (1)
packages/features/ee/billing/repository/IBillingRepository.ts (1)

44-46: Keep BillingRecord in sync with the new subscription fields.

We accept these timestamps in create, but BillingRecord still omits them, so repository implementations can’t surface the stored values without casts/any. Please extend BillingRecord (and any DTOs mirroring it) to include the optional date columns so the types stay coherent.

 export interface BillingRecord {
   id: string;
   teamId: number;
   subscriptionId: string;
   subscriptionItemId: string;
   customerId: string;
   planName: Plan;
   status: SubscriptionStatus;
+  subscriptionStart?: Date | null;
+  subscriptionTrialEnd?: Date | null;
+  subscriptionEnd?: Date | null;
 }
📜 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 19e4e84 and 343710d.

📒 Files selected for processing (1)
  • packages/features/ee/billing/repository/IBillingRepository.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*Repository.ts

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

Repository files must include Repository suffix, prefix with technology if applicable (e.g., PrismaAppRepository.ts), and use PascalCase matching the exported class

Files:

  • packages/features/ee/billing/repository/IBillingRepository.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/ee/billing/repository/IBillingRepository.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/ee/billing/repository/IBillingRepository.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/ee/billing/repository/IBillingRepository.ts

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 core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ❗️ migrations contains migration files ready-for-e2e size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants