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,7 +1,11 @@
import { Inject, Injectable } from '@nestjs/common';
import graphqlFields from 'graphql-fields';
import { capitalize, isDefined } from 'twenty-shared/utils';
import {
assertIsDefinedOrThrow,
capitalize,
isDefined,
} from 'twenty-shared/utils';
import { type ObjectLiteral } from 'typeorm';
import { type ObjectRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
@@ -24,7 +28,6 @@ import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/g
import { WorkspaceQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.service';
import { ApiKeyRoleService } from 'src/engine/core-modules/api-key/api-key-role.service';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import { type PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants';
import {
PermissionsException,
@@ -36,6 +39,7 @@ import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role
import { type WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
export type GraphqlQueryResolverExecutionArgs<Input extends ResolverArgs> = {
args: Input;
@@ -85,7 +89,7 @@ export abstract class GraphqlQueryBaseResolverService<
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace);
await this.validate(args, options);
@@ -214,7 +218,7 @@ export abstract class GraphqlQueryBaseResolverService<
const workspace = authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
if (
Object.keys(OBJECTS_WITH_SETTINGS_PERMISSIONS_REQUIREMENTS).includes(
@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils';
import {
type ObjectRecord,
@@ -23,9 +23,9 @@ import {
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
import { RecordInputTransformerService } from 'src/engine/core-modules/record-transformer/services/record-input-transformer.service';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import { type FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map';
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@Injectable()
export class QueryRunnerArgsFactory {
@@ -159,7 +159,7 @@ export class QueryRunnerArgsFactory {
const workspace = options.authContext.workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
const overriddenPositionRecords =
await this.recordPositionService.overridePositionOnRecords({
@@ -3,6 +3,8 @@ import { DiscoveryService, ModuleRef, createContextId } from '@nestjs/core';
import { Injector } from '@nestjs/core/injector/injector';
import { type Module } from '@nestjs/core/injector/module';
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
import { type ObjectRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
import { type QueryResultFieldValue } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-field-value';
import {
@@ -22,7 +24,7 @@ import { type WorkspaceQueryHookKey } from 'src/engine/api/graphql/workspace-que
import { WorkspaceQueryHookStorage } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/storage/workspace-query-hook.storage';
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
import { WorkspaceQueryHookMetadataAccessor } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook-metadata.accessor';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
@Injectable()
export class WorkspaceQueryHookExplorer implements OnModuleInit {
@@ -92,7 +94,7 @@ export class WorkspaceQueryHookExplorer implements OnModuleInit {
const workspace = executeParams?.[0].workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
if (isRequestScoped) {
const contextId = createContextId();
@@ -159,7 +161,7 @@ export class WorkspaceQueryHookExplorer implements OnModuleInit {
const workspace = executeParams?.[0].workspace;
workspaceValidator.assertIsDefinedOrThrow(workspace);
assertIsDefinedOrThrow(workspace, WorkspaceNotFoundDefaultError);
const transformedPayload = this.transformPayload(executeParams[2]);