fix(server): workspace sub status (#15155)

#### PR Dependency Tree


* **PR #15155** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
This commit is contained in:
DarkSky
2026-06-26 17:07:56 +08:00
committed by GitHub
parent 57c5bac456
commit 8e036a2f38
4 changed files with 66 additions and 5 deletions
@@ -145,6 +145,28 @@ e2e('should set new invited users to waiting-seat status', async t => {
t.is(invitationInfo.status, WorkspaceMemberStatus.NeedMoreSeat);
});
e2e('should allocate existing team seats for new invited users', async t => {
const { owner, workspace } = await createTeamWorkspace(4);
await app.login(owner);
const u1 = await app.createUser();
const result = await app.gql({
query: inviteByEmailsMutation,
variables: {
workspaceId: workspace.id,
emails: [u1.email],
},
});
t.not(result.inviteMembers[0].inviteId, null);
const invitationInfo = await getInvitationInfo(
result.inviteMembers[0].inviteId!
);
t.is(invitationInfo.status, WorkspaceMemberStatus.Pending);
});
e2e('should allocate seats', async t => {
const { owner, workspace } = await createTeamWorkspace();
await app.login(owner);
@@ -1475,6 +1475,41 @@ test('should not be able to checkout for workspace if subscribed', async t => {
);
});
test('should be able to checkout for workspace after canceled subscription', async t => {
const { service, u1, db, stripe } = t.context;
await db.subscription.create({
data: {
targetId: 'ws_1',
stripeSubscriptionId: 'sub_1',
plan: SubscriptionPlan.Team,
recurring: SubscriptionRecurring.Monthly,
status: SubscriptionStatus.Canceled,
start: new Date(Date.now() - 100000),
end: new Date(Date.now() - 1000),
quantity: 1,
},
});
await service.checkout(
{
plan: SubscriptionPlan.Team,
recurring: SubscriptionRecurring.Monthly,
variant: null,
successCallbackLink: '',
},
{
user: u1,
workspaceId: 'ws_1',
}
);
t.deepEqual(getLastCheckoutPrice(stripe.checkout.sessions.create), {
price: TEAM_MONTHLY,
coupon: undefined,
});
});
const teamSub: Stripe.Subscription = {
...sub,
items: {
@@ -243,10 +243,8 @@ export class WorkspaceMemberResolver {
inviterId: me.id,
}
);
results.push({
email,
inviteId: role.id,
});
await this.allocateAvailableTeamSeats(workspaceId, quota.memberLimit);
results.push({ email, inviteId: role.id });
} else {
const needMoreSeat = quota.memberCount + idx + 1 > quota.memberLimit;
if (needMoreSeat) {
@@ -404,6 +402,7 @@ export class WorkspaceMemberResolver {
inviterId: me.id,
}
);
await this.allocateAvailableTeamSeats(workspaceId, quota.memberLimit);
} else {
if (quota.memberCount >= quota.memberLimit) {
throw new NoMoreSeat({ spaceId: workspaceId });
@@ -717,4 +716,9 @@ export class WorkspaceMemberResolver {
throw new SpaceAccessDenied({ spaceId: workspaceId });
}
}
private async allocateAvailableTeamSeats(workspaceId: string, limit: number) {
if (limit <= 0) return;
await this.workspaceService.allocateSeats(workspaceId, limit);
}
}
@@ -72,7 +72,7 @@ export class WorkspaceSubscriptionManager extends SubscriptionManager {
params: z.infer<typeof CheckoutParams>,
args: z.infer<typeof WorkspaceSubscriptionCheckoutArgs>
) {
const subscription = await this.getSubscription({
const subscription = await this.getActiveSubscription({
plan: SubscriptionPlan.Team,
workspaceId: args.workspaceId,
});