Conversation
WalkthroughThis change adds two async helper methods to OrganizationBillingPortalService: getValidatedTeamSubscriptionId(metadata) and getValidatedTeamSubscriptionIdForPlatform(subscriptionId?). getCustomerId is refactored to use these helpers. For platform teams, it reads subscriptionId from team.platformBilling?.subscriptionId; for non-platform teams, it validates and extracts the subscriptionId from team metadata. If no valid subscriptionId is found, it returns null. When a subscriptionId exists, it fetches the subscription, checks for a customer ID, and logs a warning if missing. Error handling logic remains as before. Possibly related PRs
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.ts (2)
27-35: Consider making this helper synchronous and private.There’s no asynchronous work here, so
asynconly adds promise churn. Making itprivatealso keeps the service surface area tight.- async getValidatedTeamSubscriptionId(metadata: Prisma.JsonValue) { + private getValidatedTeamSubscriptionId(metadata: Prisma.JsonValue) {Outside this hunk, the call site can drop the
await:const subscriptionId = this.getValidatedTeamSubscriptionId(team.metadata);
37-43: Same here—no need forasync, andprivateclarifies intent.This helper is purely synchronous and only used internally, so we can trim the promise wrapper and hide it from the public API.
- async getValidatedTeamSubscriptionIdForPlatform(subscriptionId?: string | null) { + private getValidatedTeamSubscriptionIdForPlatform(subscriptionId?: string | null) {Then update the call site accordingly:
const subscriptionId = this.getValidatedTeamSubscriptionIdForPlatform( team.platformBilling?.subscriptionId );
📜 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.
📒 Files selected for processing (1)
packages/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*Service.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Service files must include
Servicesuffix, use PascalCase matching exported class, and avoid generic names (e.g.,MembershipService.ts)
Files:
packages/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.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/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.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/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.ts
🧠 Learnings (1)
📚 Learning: 2025-09-09T03:29:43.025Z
Learnt from: emrysal
PR: calcom/cal.com#23692
File: packages/lib/server/service/InsightsBookingBaseService.ts:16-16
Timestamp: 2025-09-09T03:29:43.025Z
Learning: In the Cal.com codebase, readonlyPrisma is still an instance of PrismaClient, making type changes from `typeof readonlyPrisma` to `PrismaClient` less critical since they are fundamentally compatible types.
Applied to files:
packages/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.ts
🧬 Code graph analysis (1)
packages/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.ts (1)
packages/app-store/stripepayment/lib/subscriptions.ts (1)
getSubscriptionFromId(31-33)
🔇 Additional comments (3)
packages/app-store/stripepayment/lib/services/organization/OrganizationBillingPortalService.ts (3)
2-2: Import keeps metadata validation strongly typed.Pulling in
Prisma.JsonValuehere makes the helper signatures explicit and keeps validation aligned with Prisma’s JSON typing. Nice touch.
48-65: Clear branching for platform vs. classic teams.Splitting the subscription lookup paths like this makes the platform handling much easier to follow and keeps the early returns tight.
68-74: Nice reuse of the validated ID in logging.Threading the vetted
subscriptionIdthrough to the warning keeps the log actionable without re-reading metadata.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
E2E results are ready! |
What does this PR do?
TeamBillingPortalService.tsto handle platform team billing, but the billing portal in the platform dashboard actually usesOrganizationBillingPortalService.tshence org billing service needs to be updated as well.