Skip to content

Commit b312955

Browse files
feat: Add subscription start, trial end, and dates to billing tables (calcom#24408)
* Add subscription start, trial end, and end dates to db * Add subscription start, trial end, and end date to db * Write subscription start date on new team subscriptions * Write subscription start date for new orgs * Fix typo in stripe billing service file (billling -> billing) * Use `StripeBillingService.extractSubscriptionDates` * Remove comments * Address comment * Fix typo in file import * Fix typo in file import * Add missing SubscriptionStatus enum values - 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: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent 003aaaa commit b312955

20 files changed

Lines changed: 107 additions & 25 deletions

File tree

apps/web/app/api/teams/api/create/route.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type Stripe from "stripe";
55
import { z } from "zod";
66

77
import { Plan, SubscriptionStatus } from "@calcom/features/ee/billing/repository/IBillingRepository";
8+
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service";
89
import { InternalTeamBilling } from "@calcom/features/ee/billing/teams/internal-team-billing";
910
import stripe from "@calcom/features/ee/payments/server/stripe";
1011
import { HttpError } from "@calcom/lib/http-error";
@@ -57,6 +58,9 @@ async function handler(request: NextRequest) {
5758
});
5859

5960
if (checkoutSessionSubscription) {
61+
const { subscriptionStart } =
62+
StripeBillingService.extractSubscriptionDates(checkoutSessionSubscription);
63+
6064
const internalBillingService = new InternalTeamBilling(finalizedTeam);
6165
await internalBillingService.saveTeamBilling({
6266
teamId: finalizedTeam.id,
@@ -66,6 +70,7 @@ async function handler(request: NextRequest) {
6670
// TODO: Implement true subscription status when webhook events are implemented
6771
status: SubscriptionStatus.ACTIVE,
6872
planName: Plan.TEAM,
73+
subscriptionStart,
6974
});
7075
}
7176

apps/web/app/api/teams/create/route.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type Stripe from "stripe";
55
import { z } from "zod";
66

77
import { Plan, SubscriptionStatus } from "@calcom/features/ee/billing/repository/IBillingRepository";
8+
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service";
89
import { InternalTeamBilling } from "@calcom/features/ee/billing/teams/internal-team-billing";
910
import stripe from "@calcom/features/ee/payments/server/stripe";
1011
import { HttpError } from "@calcom/lib/http-error";
@@ -87,6 +88,7 @@ async function getHandler(req: NextRequest) {
8788
});
8889

8990
if (checkoutSession && subscription) {
91+
const { subscriptionStart } = StripeBillingService.extractSubscriptionDates(subscription);
9092
const internalBillingService = new InternalTeamBilling(team);
9193
await internalBillingService.saveTeamBilling({
9294
teamId: team.id,
@@ -96,6 +98,7 @@ async function getHandler(req: NextRequest) {
9698
// TODO: Implement true subscription status when webhook events are implemented
9799
status: SubscriptionStatus.ACTIVE,
98100
planName: Plan.TEAM,
101+
subscriptionStart,
99102
});
100103
}
101104

apps/web/lib/pages/auth/verify-email.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ vi.mock("@calcom/prisma", () => {
1717
};
1818
});
1919

20-
vi.mock("@calcom/features/ee/billing/stripe-billling-service", () => {
20+
vi.mock("@calcom/features/ee/billing/stripe-billing-service", () => {
2121
return {
2222
StripeBillingService: vi.fn(),
2323
};

apps/web/lib/pages/auth/verify-email.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from "next";
22
import { z } from "zod";
33

44
import dayjs from "@calcom/dayjs";
5-
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
5+
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service";
66
import { WEBAPP_URL } from "@calcom/lib/constants";
77
import { IS_STRIPE_ENABLED } from "@calcom/lib/constants";
88
import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository";

packages/app-store/stripepayment/lib/getCustomerAndCheckoutSession.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
1+
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service";
22

33
export async function getCustomerAndCheckoutSession(checkoutSessionId: string) {
44
const billingService = new StripeBillingService();

packages/features/auth/signup/handlers/calcomHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { getLocaleFromRequest } from "@calcom/features/auth/lib/getLocaleFromReq
66
import { sendEmailVerification } from "@calcom/features/auth/lib/verifyEmail";
77
import { createOrUpdateMemberships } from "@calcom/features/auth/signup/utils/createOrUpdateMemberships";
88
import { prefillAvatar } from "@calcom/features/auth/signup/utils/prefillAvatar";
9-
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
9+
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service";
1010
import { sentrySpan } from "@calcom/features/watchlist/lib/telemetry";
1111
import { checkIfEmailIsBlockedInWatchlistController } from "@calcom/features/watchlist/operations/check-if-email-in-watchlist.controller";
1212
import { hashPassword } from "@calcom/lib/auth/hashPassword";

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { z } from "zod";
22

33
import { Plan, SubscriptionStatus } from "@calcom/features/ee/billing/repository/IBillingRepository";
4+
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service";
45
import { InternalTeamBilling } from "@calcom/features/ee/billing/teams/internal-team-billing";
56
import { createOrganizationFromOnboarding } from "@calcom/features/ee/organizations/lib/server/createOrganizationFromOnboarding";
7+
import stripe from "@calcom/features/ee/payments/server/stripe";
68
import logger from "@calcom/lib/logger";
79
import { safeStringify } from "@calcom/lib/safeStringify";
810
import { OrganizationOnboardingRepository } from "@calcom/lib/server/repository/organizationOnboarding";
@@ -96,6 +98,10 @@ const handler = async (data: SWHMap["invoice.paid"]["data"]) => {
9698
paymentSubscriptionItemId,
9799
});
98100

101+
// Get the Stripe subscription object
102+
const stripeSubscription = await stripe.subscriptions.retrieve(paymentSubscriptionId);
103+
const { subscriptionStart } = StripeBillingService.extractSubscriptionDates(stripeSubscription);
104+
99105
const internalTeamBillingService = new InternalTeamBilling(organization);
100106
await internalTeamBillingService.saveTeamBilling({
101107
teamId: organization.id,
@@ -105,6 +111,7 @@ const handler = async (data: SWHMap["invoice.paid"]["data"]) => {
105111
// TODO: Write actual status when webhook events are added
106112
status: SubscriptionStatus.ACTIVE,
107113
planName: Plan.ORGANIZATION,
114+
subscriptionStart,
108115
});
109116

110117
logger.debug(`Marking onboarding as complete for organization ${organization.id}`);

packages/features/ee/billing/billing-service-factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StripeBillingService } from "./stripe-billling-service";
1+
import { StripeBillingService } from "./stripe-billing-service";
22

33
export class BillingFactory {
44
constructor() {

packages/features/ee/billing/credit-service.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { TeamRepository } from "@calcom/lib/server/repository/team";
99
import { CreditType } from "@calcom/prisma/enums";
1010

1111
import { CreditService } from "./credit-service";
12-
import { StripeBillingService } from "./stripe-billling-service";
12+
import { StripeBillingService } from "./stripe-billing-service";
1313
import { InternalTeamBilling } from "./teams/internal-team-billing";
1414

1515
const MOCK_TX = {};

packages/features/ee/billing/credit-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
sendCreditBalanceLimitReachedEmails,
66
sendCreditBalanceLowWarningEmails,
77
} from "@calcom/emails/email-manager";
8-
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
8+
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service";
99
import { InternalTeamBilling } from "@calcom/features/ee/billing/teams/internal-team-billing";
1010
import { cancelScheduledMessagesAndScheduleEmails } from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler";
1111
import { IS_SMS_CREDITS_ENABLED } from "@calcom/lib/constants";

0 commit comments

Comments
 (0)