diff --git a/packages/backend/server/src/core/quota/service.ts b/packages/backend/server/src/core/quota/service.ts index fa519809f4..54969d4484 100644 --- a/packages/backend/server/src/core/quota/service.ts +++ b/packages/backend/server/src/core/quota/service.ts @@ -142,12 +142,16 @@ export class QuotaService { const usedStorageQuota = quota.ownerQuota ? await this.getUserStorageUsage(quota.ownerQuota) : await this.getWorkspaceStorageUsage(workspaceId); - const memberCount = await this.models.workspaceUser.count(workspaceId); + const memberCount = + await this.models.workspaceUser.chargedCount(workspaceId); + const overcapacityMemberCount = + await this.models.workspaceUser.insufficientSeatMemberCount(workspaceId); return { ...quota, usedStorageQuota, memberCount, + overcapacityMemberCount, usedSize: usedStorageQuota, }; } @@ -203,6 +207,7 @@ export class QuotaService { historyPeriod: formatDate(quota.historyPeriod), memberLimit: quota.memberLimit.toString(), memberCount: quota.memberCount.toString(), + overcapacityMemberCount: quota.overcapacityMemberCount.toString(), }; } diff --git a/packages/backend/server/src/core/quota/types.ts b/packages/backend/server/src/core/quota/types.ts index fbe6f41ddc..31da198edf 100644 --- a/packages/backend/server/src/core/quota/types.ts +++ b/packages/backend/server/src/core/quota/types.ts @@ -85,6 +85,9 @@ export class WorkspaceQuotaHumanReadableType { @Field() memberCount!: string; + + @Field() + overcapacityMemberCount!: string; } @ObjectType() @@ -110,6 +113,9 @@ export class WorkspaceQuotaType implements Partial { @Field() memberCount!: number; + @Field() + overcapacityMemberCount!: number; + @Field() humanReadable!: WorkspaceQuotaHumanReadableType; diff --git a/packages/backend/server/src/models/workspace-user.ts b/packages/backend/server/src/models/workspace-user.ts index 18ea90af9b..d5b47225f7 100644 --- a/packages/backend/server/src/models/workspace-user.ts +++ b/packages/backend/server/src/models/workspace-user.ts @@ -289,6 +289,15 @@ export class WorkspaceUserModel extends BaseModel { }); } + async insufficientSeatMemberCount(workspaceId: string) { + return this.db.workspaceUserRole.count({ + where: { + workspaceId, + status: WorkspaceMemberStatus.NeedMoreSeat, + }, + }); + } + async getUserActiveRoles( userId: string, filter: { role?: WorkspaceRole } = {} diff --git a/packages/backend/server/src/schema.gql b/packages/backend/server/src/schema.gql index e26e0c93de..9d0a3bcac8 100644 --- a/packages/backend/server/src/schema.gql +++ b/packages/backend/server/src/schema.gql @@ -1746,6 +1746,7 @@ type WorkspaceQuotaHumanReadableType { memberCount: String! memberLimit: String! name: String! + overcapacityMemberCount: String! storageQuota: String! storageQuotaUsed: String! } @@ -1757,6 +1758,7 @@ type WorkspaceQuotaType { memberCount: Int! memberLimit: Int! name: String! + overcapacityMemberCount: Int! storageQuota: SafeInt! usedSize: SafeInt! @deprecated(reason: "use `usedStorageQuota` instead") usedStorageQuota: SafeInt! diff --git a/packages/common/graphql/src/graphql/index.ts b/packages/common/graphql/src/graphql/index.ts index ae8aad6356..ce1f5dff0c 100644 --- a/packages/common/graphql/src/graphql/index.ts +++ b/packages/common/graphql/src/graphql/index.ts @@ -1821,12 +1821,15 @@ export const workspaceQuotaQuery = { historyPeriod memberLimit memberCount + overcapacityMemberCount humanReadable { name blobLimit storageQuota historyPeriod memberLimit + memberCount + overcapacityMemberCount } } } diff --git a/packages/common/graphql/src/graphql/workspace-quota.gql b/packages/common/graphql/src/graphql/workspace-quota.gql index 7d51730c15..0f7c76aedc 100644 --- a/packages/common/graphql/src/graphql/workspace-quota.gql +++ b/packages/common/graphql/src/graphql/workspace-quota.gql @@ -8,12 +8,15 @@ query workspaceQuota($id: String!) { historyPeriod memberLimit memberCount + overcapacityMemberCount humanReadable { name blobLimit storageQuota historyPeriod memberLimit + memberCount + overcapacityMemberCount } } } diff --git a/packages/common/graphql/src/schema.ts b/packages/common/graphql/src/schema.ts index 8761c1c4ea..7f48a60dae 100644 --- a/packages/common/graphql/src/schema.ts +++ b/packages/common/graphql/src/schema.ts @@ -2310,6 +2310,7 @@ export interface WorkspaceQuotaHumanReadableType { memberCount: Scalars['String']['output']; memberLimit: Scalars['String']['output']; name: Scalars['String']['output']; + overcapacityMemberCount: Scalars['String']['output']; storageQuota: Scalars['String']['output']; storageQuotaUsed: Scalars['String']['output']; } @@ -2322,6 +2323,7 @@ export interface WorkspaceQuotaType { memberCount: Scalars['Int']['output']; memberLimit: Scalars['Int']['output']; name: Scalars['String']['output']; + overcapacityMemberCount: Scalars['Int']['output']; storageQuota: Scalars['SafeInt']['output']; /** @deprecated use `usedStorageQuota` instead */ usedSize: Scalars['SafeInt']['output']; @@ -4498,6 +4500,7 @@ export type WorkspaceQuotaQuery = { historyPeriod: number; memberLimit: number; memberCount: number; + overcapacityMemberCount: number; humanReadable: { __typename?: 'WorkspaceQuotaHumanReadableType'; name: string; @@ -4505,6 +4508,8 @@ export type WorkspaceQuotaQuery = { storageQuota: string; historyPeriod: string; memberLimit: string; + memberCount: string; + overcapacityMemberCount: string; }; }; };