Skip to content

Commit d3e5716

Browse files
committed
[server] Refactor StripeService.findCustomer and .findUncancelledSubscription to only use attributionIds
1 parent cfa3bed commit d3e5716

File tree

6 files changed

+45
-61
lines changed

6 files changed

+45
-61
lines changed

components/server/ee/src/billing/billing-mode.spec.db.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,21 @@ class StripeServiceMock extends StripeService {
5050
super();
5151
}
5252

53-
async findUncancelledSubscriptionByCustomer(customerId: string): Promise<string | undefined> {
54-
if (this.subscription?.customer === customerId) {
53+
async findUncancelledSubscriptionByAttributionId(attributionId: string): Promise<string | undefined> {
54+
const customerId = await this.findCustomerByAttributionId(attributionId);
55+
if (!!customerId && this.subscription?.customer === customerId) {
5556
return this.subscription.id;
5657
}
5758
return undefined;
5859
}
5960

60-
async findCustomerByUserId(userId: string): Promise<string | undefined> {
61+
async findCustomerByAttributionId(attributionId: string): Promise<string | undefined> {
6162
const customerId = this.subscription?.customer;
6263
if (!customerId) {
6364
return undefined;
6465
}
6566
return customerId;
6667
}
67-
68-
async findCustomerByTeamId(teamId: string): Promise<string | undefined> {
69-
return this.findCustomerByUserId(teamId);
70-
}
7168
}
7269

7370
class ConfigCatClientMock implements Client {

components/server/ee/src/billing/billing-mode.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class BillingModesImpl implements BillingModes {
4141
@inject(Config) protected readonly config: Config;
4242
@inject(ConfigCatClientFactory) protected readonly configCatClientFactory: ConfigCatClientFactory;
4343
@inject(SubscriptionService) protected readonly subscriptionSvc: SubscriptionService;
44-
@inject(StripeService) protected readonly stripeSvc: StripeService;
44+
@inject(StripeService) protected readonly stripeService: StripeService;
4545
@inject(TeamSubscriptionDB) protected readonly teamSubscriptionDb: TeamSubscriptionDB;
4646
@inject(TeamSubscription2DB) protected readonly teamSubscription2Db: TeamSubscription2DB;
4747
@inject(TeamDB) protected readonly teamDB: TeamDB;
@@ -116,12 +116,11 @@ export class BillingModesImpl implements BillingModes {
116116

117117
// Stripe: Active personal subsciption?
118118
let hasUbbPersonal = false;
119-
const customerId = await this.stripeSvc.findCustomerByUserId(user.id);
120-
if (customerId) {
121-
const subscriptionId = await this.stripeSvc.findUncancelledSubscriptionByCustomer(customerId);
122-
if (subscriptionId) {
123-
hasUbbPersonal = true;
124-
}
119+
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId(
120+
AttributionId.render({ kind: "user", userId: user.id }),
121+
);
122+
if (subscriptionId) {
123+
hasUbbPersonal = true;
125124
}
126125

127126
// 3. Check team memberships/plans
@@ -192,12 +191,11 @@ export class BillingModesImpl implements BillingModes {
192191

193192
// 3. Now we're usage-based. We only have to figure out whether we have a plan yet or not.
194193
const result: BillingMode = { mode: "usage-based" };
195-
const customerId = await this.stripeSvc.findCustomerByTeamId(team.id);
196-
if (customerId) {
197-
const subscriptionId = await this.stripeSvc.findUncancelledSubscriptionByCustomer(customerId);
198-
if (subscriptionId) {
199-
result.paid = true;
200-
}
194+
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId(
195+
AttributionId.render({ kind: "team", teamId: team.id }),
196+
);
197+
if (subscriptionId) {
198+
result.paid = true;
201199
}
202200
return result;
203201
}

components/server/ee/src/billing/entitlement-service-ubp.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,21 +114,18 @@ export class EntitlementServiceUBP implements EntitlementService {
114114

115115
protected async hasPaidSubscription(user: User, date: Date): Promise<boolean> {
116116
// Paid user?
117-
const customerId = await this.stripeService.findCustomerByUserId(user.id);
118-
if (customerId) {
119-
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByCustomer(customerId);
120-
if (subscriptionId) {
121-
return true;
122-
}
117+
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId(
118+
AttributionId.render({ kind: "user", userId: user.id }),
119+
);
120+
if (subscriptionId) {
121+
return true;
123122
}
124123
// Member of paid team?
125124
const teams = await this.teamDB.findTeamsByUser(user.id);
126125
const isTeamSubscribedPromises = teams.map(async (team: Team) => {
127-
const customerId = await this.stripeService.findCustomerByTeamId(team.id);
128-
if (!customerId) {
129-
return false;
130-
}
131-
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByCustomer(customerId);
126+
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId(
127+
AttributionId.render({ kind: "team", teamId: team.id }),
128+
);
132129
return !!subscriptionId;
133130
});
134131
// Return the first truthy promise, or false if all the promises were falsy.

components/server/ee/src/user/stripe-service.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,6 @@ export class StripeService {
3434
return await this.getStripe().setupIntents.create({ usage: "on_session" });
3535
}
3636

37-
async findCustomerByUserId(userId: string): Promise<string | undefined> {
38-
return this.findCustomerByAttributionId(AttributionId.render({ kind: "user", userId }));
39-
}
40-
41-
async findCustomerByTeamId(teamId: string): Promise<string | undefined> {
42-
return this.findCustomerByAttributionId(AttributionId.render({ kind: "team", teamId }));
43-
}
44-
4537
async findCustomerByAttributionId(attributionId: string): Promise<string | undefined> {
4638
const query = `metadata['attributionId']:'${attributionId}'`;
4739
const result = await this.getStripe().customers.search({ query });
@@ -119,7 +111,9 @@ export class StripeService {
119111
}
120112

121113
async getPortalUrlForTeam(team: Team): Promise<string> {
122-
const customerId = await this.findCustomerByTeamId(team.id);
114+
const customerId = await this.findCustomerByAttributionId(
115+
AttributionId.render({ kind: "team", teamId: team.id }),
116+
);
123117
if (!customerId) {
124118
throw new Error(`No Stripe Customer ID found for team '${team.id}'`);
125119
}
@@ -131,7 +125,9 @@ export class StripeService {
131125
}
132126

133127
async getPortalUrlForUser(user: User): Promise<string> {
134-
const customerId = await this.findCustomerByUserId(user.id);
128+
const customerId = await this.findCustomerByAttributionId(
129+
AttributionId.render({ kind: "user", userId: user.id }),
130+
);
135131
if (!customerId) {
136132
throw new Error(`No Stripe Customer ID found for user '${user.id}'`);
137133
}
@@ -142,7 +138,11 @@ export class StripeService {
142138
return session.url;
143139
}
144140

145-
async findUncancelledSubscriptionByCustomer(customerId: string): Promise<string | undefined> {
141+
async findUncancelledSubscriptionByAttributionId(attributionId: string): Promise<string | undefined> {
142+
const customerId = await this.findCustomerByAttributionId(attributionId);
143+
if (!customerId) {
144+
return undefined;
145+
}
146146
const result = await this.getStripe().subscriptions.list({
147147
customer: customerId,
148148
});

components/server/ee/src/workspace/gitpod-server-impl.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,12 +1596,11 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
15961596
{ teamId, chargebeeSubscriptionId },
15971597
);
15981598
}
1599-
const teamCustomerId = await this.stripeService.findCustomerByTeamId(teamId);
1600-
if (teamCustomerId) {
1601-
const subsciptionId = await this.stripeService.findUncancelledSubscriptionByCustomer(teamCustomerId);
1602-
if (subsciptionId) {
1603-
await this.stripeService.cancelSubscription(subsciptionId);
1604-
}
1599+
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId(
1600+
AttributionId.render({ kind: "team", teamId: teamId }),
1601+
);
1602+
if (subscriptionId) {
1603+
await this.stripeService.cancelSubscription(subscriptionId);
16051604
}
16061605
}
16071606

@@ -2066,12 +2065,7 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
20662065
if (attrId.kind == "team") {
20672066
await this.guardTeamOperation(attrId.teamId, "get");
20682067
}
2069-
const customerId = await this.stripeService.findCustomerByAttributionId(attributionId);
2070-
if (!customerId) {
2071-
return undefined;
2072-
}
2073-
2074-
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByCustomer(customerId);
2068+
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId(attributionId);
20752069
return subscriptionId;
20762070
} catch (error) {
20772071
log.error(`Failed to get Stripe Subscription ID for '${attributionId}'`, error);

components/server/src/user/user-service.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,9 @@ export class UserService {
196196
}
197197

198198
protected async findTeamUsageBasedSubscriptionId(team: Team): Promise<string | undefined> {
199-
const customerId = await this.stripeService.findCustomerByTeamId(team.id);
200-
if (!customerId) {
201-
return;
202-
}
203-
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByCustomer(customerId);
199+
const subscriptionId = await this.stripeService.findUncancelledSubscriptionByAttributionId(
200+
AttributionId.render({ kind: "team", teamId: team.id }),
201+
);
204202
return subscriptionId;
205203
}
206204

@@ -325,8 +323,8 @@ export class UserService {
325323
if (!membership) {
326324
throw new Error("Cannot attribute to an unrelated team.");
327325
}
328-
const teamCustomer = await this.stripeService.findCustomerByTeamId(attributionId.teamId);
329-
if (!teamCustomer) {
326+
const teamCustomerId = await this.stripeService.findCustomerByAttributionId(usageAttributionId);
327+
if (!teamCustomerId) {
330328
throw new Error("Cannot attribute to team without Stripe customer.");
331329
}
332330
user.usageAttributionId = usageAttributionId;

0 commit comments

Comments
 (0)