fix(server): avoid error when other prices added but logic is not released (#6191)

This commit is contained in:
Brooooooklyn
2024-03-22 08:39:11 +00:00
parent 75355867c7
commit aecc523663
6 changed files with 48 additions and 75 deletions

View File

@@ -1,8 +1,4 @@
import {
BadGatewayException,
ForbiddenException,
InternalServerErrorException,
} from '@nestjs/common';
import { BadGatewayException, ForbiddenException } from '@nestjs/common';
import {
Args,
Context,
@@ -48,11 +44,11 @@ class SubscriptionPrice {
@Field()
currency!: string;
@Field()
amount!: number;
@Field(() => Int, { nullable: true })
amount?: number | null;
@Field()
yearlyAmount!: number;
@Field(() => Int, { nullable: true })
yearlyAmount?: number | null;
}
@ObjectType('UserSubscription')
@@ -176,64 +172,39 @@ export class SubscriptionResolver {
}
);
return Object.entries(group).map(([plan, prices]) => {
const yearly = prices.find(
price =>
decodeLookupKey(
// @ts-expect-error empty lookup key is filtered out
price.lookup_key
)[1] === SubscriptionRecurring.Yearly
);
const monthly = prices.find(
price =>
decodeLookupKey(
// @ts-expect-error empty lookup key is filtered out
price.lookup_key
)[1] === SubscriptionRecurring.Monthly
);
function findPrice(plan: SubscriptionPlan) {
const prices = group[plan];
if (!yearly || !monthly) {
throw new InternalServerErrorException(
'The prices are not configured correctly.'
);
if (!prices) {
return null;
}
const monthlyPrice = prices.find(p => p.recurring?.interval === 'month');
const yearlyPrice = prices.find(p => p.recurring?.interval === 'year');
const currency = monthlyPrice?.currency ?? yearlyPrice?.currency ?? 'usd';
return {
type: 'fixed',
plan: plan as SubscriptionPlan,
currency: monthly.currency,
amount: monthly.unit_amount ?? 0,
yearlyAmount: yearly.unit_amount ?? 0,
currency,
amount: monthlyPrice?.unit_amount,
yearlyAmount: yearlyPrice?.unit_amount,
};
}
// extend it when new plans are added
const fixedPlans = [SubscriptionPlan.Pro];
return fixedPlans.reduce((prices, plan) => {
const price = findPrice(plan);
if (price && (price.amount || price.yearlyAmount)) {
prices.push({
type: 'fixed',
plan,
...price,
});
}
/**
* @deprecated
*/
@Mutation(() => String, {
deprecationReason: 'use `createCheckoutSession` instead',
description: 'Create a subscription checkout link of stripe',
})
async checkout(
@CurrentUser() user: CurrentUser,
@Args({ name: 'recurring', type: () => SubscriptionRecurring })
recurring: SubscriptionRecurring,
@Args('idempotencyKey') idempotencyKey: string
) {
const session = await this.service.createCheckoutSession({
user,
plan: SubscriptionPlan.Pro,
recurring,
redirectUrl: `${this.config.baseUrl}/upgrade-success`,
idempotencyKey,
});
if (!session.url) {
throw new BadGatewayException('Failed to create checkout session.');
}
return session.url;
return prices;
}, [] as SubscriptionPrice[]);
}
@Mutation(() => String, {

View File

@@ -65,7 +65,9 @@ export class SubscriptionService {
) {}
async listPrices() {
return this.stripe.prices.list();
return this.stripe.prices.list({
active: true,
});
}
async createCheckoutSession({

View File

@@ -114,9 +114,6 @@ type Mutation {
changeEmail(email: String!, token: String!): UserType!
changePassword(newPassword: String!, token: String!): UserType!
"""Create a subscription checkout link of stripe"""
checkout(idempotencyKey: String!, recurring: SubscriptionRecurring!): String! @deprecated(reason: "use `createCheckoutSession` instead")
"""Create a subscription checkout link of stripe"""
createCheckoutSession(input: CreateCheckoutSessionInput!): String!
@@ -275,11 +272,11 @@ enum SubscriptionPlan {
}
type SubscriptionPrice {
amount: Int!
amount: Int
currency: String!
plan: SubscriptionPlan!
type: String!
yearlyAmount: Int!
yearlyAmount: Int
}
enum SubscriptionRecurring {

View File

@@ -108,8 +108,8 @@ const SubscriptionSettings = () => {
? '0'
: price
? recurring === SubscriptionRecurring.Monthly
? String(price.amount / 100)
: String(price.yearlyAmount / 100)
? String((price.amount ?? 0) / 100)
: String((price.yearlyAmount ?? 0) / 100)
: '?';
const t = useAFFiNEI18N();

View File

@@ -51,11 +51,14 @@ const Settings = () => {
const detail = planDetail.get(price.plan);
if (detail?.type === 'fixed') {
detail.price = (price.amount / 100).toFixed(2);
detail.yearlyPrice = (price.yearlyAmount / 100 / 12).toFixed(2);
detail.discount = Math.floor(
detail.price = ((price.amount ?? 0) / 100).toFixed(2);
detail.yearlyPrice = ((price.yearlyAmount ?? 0) / 100 / 12).toFixed(2);
detail.discount =
price.yearlyAmount && price.amount
? Math.floor(
(1 - price.yearlyAmount / 12 / price.amount) * 100
).toString();
).toString()
: undefined;
}
});

View File

@@ -538,8 +538,8 @@ export type PricesQuery = {
type: string;
plan: SubscriptionPlan;
currency: string;
amount: number;
yearlyAmount: number;
amount: number | null;
yearlyAmount: number | null;
}>;
};