feat: Add team billing tables (#24148)

* Init billing tables

* Create `IBillingRepository` types

* Create billing repositories

* Create billingRepositoryFactory

* Eslint fix - remove unused organizationOnboarding

* internal-team-billing create saveTeamBilling method using repositories

* On new teams write to team billing table

* On new org write to org billing table

* Change fields to organizationId

* Add todo comment

* Revert "Change fields to organizationId"

This reverts commit bbb2e5dfa6b4c20a8a395f5730848a492cd70d68.

* test: add comprehensive tests for team billing tables

- Fix credit-service.test.ts Prisma mock to export prisma object
- Replace any types with proper TypeScript types in credit-service.test.ts
- Add unit tests for PrismaTeamBillingRepository covering record creation, enum casting, and error handling
- Add unit tests for PrismaOrganizationBillingRepository with same coverage
- Add unit tests for BillingRepositoryFactory to verify correct repository selection
- Add unit tests for InternalTeamBilling.saveTeamBilling() method testing delegation to correct repositories
- All 53 tests pass with TZ=UTC yarn test
- Type checking passes with yarn type-check:ci --force

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* refactor: update saveTeamBilling tests to mock repository interface

- Replace prismaMock usage with BillingRepositoryFactory mock
- Mock IBillingRepository interface instead of Prisma directly
- Follow repository mocking pattern from handleResponse.test.ts
- All tests passing (53 total)

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* Remove log statement

* Remove repository tests

* Address feedback

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Joe Au-Yeung
2025-10-07 14:25:31 -04:00
committed by GitHub
co-authored by joe@cal.com <j.auyeung419@gmail.com> Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent 92169eb0d2
commit c702da0334
13 changed files with 446 additions and 12 deletions
+16 -1
View File
@@ -4,9 +4,11 @@ import { NextResponse } from "next/server";
import type Stripe from "stripe";
import { z } from "zod";
import { Plan, SubscriptionStatus } from "@calcom/features/ee/billing/repository/IBillingRepository";
import { InternalTeamBilling } from "@calcom/features/ee/billing/teams/internal-team-billing";
import stripe from "@calcom/features/ee/payments/server/stripe";
import { HttpError } from "@calcom/lib/http-error";
import prisma from "@calcom/prisma";
import { prisma } from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
import { MembershipSchema } from "@calcom/prisma/zod/modelSchema/MembershipSchema";
import { TeamSchema } from "@calcom/prisma/zod/modelSchema/TeamSchema";
@@ -54,6 +56,19 @@ async function handler(request: NextRequest) {
include: { members: true },
});
if (checkoutSessionSubscription) {
const internalBillingService = new InternalTeamBilling(finalizedTeam);
await internalBillingService.saveTeamBilling({
teamId: finalizedTeam.id,
subscriptionId: checkoutSessionSubscription.id,
subscriptionItemId: checkoutSessionSubscription.items.data[0].id,
customerId: checkoutSessionSubscription.customer as string,
// TODO: Implement true subscription status when webhook events are implemented
status: SubscriptionStatus.ACTIVE,
planName: Plan.TEAM,
});
}
const response = {
message: `Team created successfully. We also made user with ID=${checkoutSessionMetadata.ownerId} the owner of this team.`,
team: schemaTeamReadPublic.parse(finalizedTeam),