feat(billing): refacto billing (#14243)

… prices for metered billing

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Antoine Moreaux
2025-09-19 11:25:53 +02:00
committed by GitHub
parent 163890f6c8
commit 43e0cd5d05
351 changed files with 16091 additions and 6101 deletions
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.createMany`)
export class WorkspaceMemberCreateManyPreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberCreateManyPreQueryHook
async execute(authContext: AuthContext): Promise<CreateManyResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type CreateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.createOne`)
export class WorkspaceMemberCreateOnePreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberCreateOnePreQueryHook
async execute(authContext: AuthContext): Promise<CreateOneResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type DeleteManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.deleteMany`)
export class WorkspaceMemberDeleteManyPreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberDeleteManyPreQueryHook
async execute(authContext: AuthContext): Promise<DeleteManyResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -1,6 +1,6 @@
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
@@ -9,7 +9,6 @@ import { type DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-res
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
@@ -18,6 +17,7 @@ import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { WorkspaceMemberPreQueryHookService } from 'src/modules/workspace-member/query-hooks/workspace-member-pre-query-hook.service';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.deleteOne`)
export class WorkspaceMemberDeleteOnePreQueryHook
@@ -39,7 +39,7 @@ export class WorkspaceMemberDeleteOnePreQueryHook
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
await this.workspaceMemberPreQueryHookService.validateWorkspaceMemberUpdatePermissionOrThrow(
{
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type DeleteManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.destroyMany`)
export class WorkspaceMemberDestroyManyPreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberDestroyManyPreQueryHook
async execute(authContext: AuthContext): Promise<DeleteManyResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.destroyOne`)
export class WorkspaceMemberDestroyOnePreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberDestroyOnePreQueryHook
async execute(authContext: AuthContext): Promise<DeleteOneResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type RestoreManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.restoreMany`)
export class WorkspaceMemberRestoreManyPreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberRestoreManyPreQueryHook
async execute(authContext: AuthContext): Promise<RestoreManyResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type RestoreOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.restoreOne`)
export class WorkspaceMemberRestoreOnePreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberRestoreOnePreQueryHook
async execute(authContext: AuthContext): Promise<RestoreOneResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -1,14 +1,16 @@
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type UpdateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
PermissionsException,
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.updateMany`)
export class WorkspaceMemberUpdateManyPreQueryHook
@@ -19,7 +21,7 @@ export class WorkspaceMemberUpdateManyPreQueryHook
async execute(authContext: AuthContext): Promise<UpdateManyResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
throw new PermissionsException(
PermissionsExceptionMessage.PERMISSION_DENIED,
@@ -2,6 +2,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'class-validator';
import { Repository } from 'typeorm';
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type WorkspacePreQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
import { type UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
@@ -13,8 +14,8 @@ import {
} from 'src/engine/core-modules/auth/auth.exception';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import { WorkspaceMemberPreQueryHookService } from 'src/modules/workspace-member/query-hooks/workspace-member-pre-query-hook.service';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@WorkspaceQueryHook(`workspaceMember.updateOne`)
export class WorkspaceMemberUpdateOnePreQueryHook
@@ -33,7 +34,7 @@ export class WorkspaceMemberUpdateOnePreQueryHook
): Promise<UpdateOneResolverArgs> {
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
await this.workspaceMemberPreQueryHookService.validateWorkspaceMemberUpdatePermissionOrThrow(
{