feat(server): support query overcapacity member count of workspace (#12050)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Workspace quota information now includes a new metric: the count of members exceeding seat capacity ("overcapacityMemberCount"), available in both numeric and human-readable formats.
  - The workspace quota display and related queries have been updated to show this new overcapacity member count alongside existing quota metrics.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
forehalo
2025-04-30 09:47:50 +00:00
parent 04531508cb
commit f1605e246b
7 changed files with 34 additions and 1 deletions

View File

@@ -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(),
};
}

View File

@@ -85,6 +85,9 @@ export class WorkspaceQuotaHumanReadableType {
@Field()
memberCount!: string;
@Field()
overcapacityMemberCount!: string;
}
@ObjectType()
@@ -110,6 +113,9 @@ export class WorkspaceQuotaType implements Partial<WorkspaceQuota> {
@Field()
memberCount!: number;
@Field()
overcapacityMemberCount!: number;
@Field()
humanReadable!: WorkspaceQuotaHumanReadableType;

View File

@@ -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 } = {}

View File

@@ -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!

View File

@@ -1821,12 +1821,15 @@ export const workspaceQuotaQuery = {
historyPeriod
memberLimit
memberCount
overcapacityMemberCount
humanReadable {
name
blobLimit
storageQuota
historyPeriod
memberLimit
memberCount
overcapacityMemberCount
}
}
}

View File

@@ -8,12 +8,15 @@ query workspaceQuota($id: String!) {
historyPeriod
memberLimit
memberCount
overcapacityMemberCount
humanReadable {
name
blobLimit
storageQuota
historyPeriod
memberLimit
memberCount
overcapacityMemberCount
}
}
}

View File

@@ -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;
};
};
};