diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index 8cdaa85113a..1a2d277b4a7 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -1484,6 +1484,7 @@ enum BillingUsageType { """The different billing products available""" enum BillingProductKey { BASE_PRODUCT + RESOURCE_CREDIT WORKFLOW_NODE_EXECUTION } @@ -1492,6 +1493,7 @@ type BillingPriceLicensed { unitAmount: Float! stripePriceId: String! priceUsageType: BillingUsageType! + creditAmount: Float } enum SubscriptionInterval { @@ -1590,7 +1592,8 @@ type BillingMeteredProductUsage { type BillingPlan { planKey: BillingPlanKey! - licensedProducts: [BillingLicensedProduct!]! + baseProducts: [BillingLicensedProduct!]! + resourceCreditProducts: [BillingLicensedProduct!]! meteredProducts: [BillingMeteredProduct!]! } @@ -1754,6 +1757,7 @@ enum FeatureFlagKey { IS_RICH_TEXT_V1_MIGRATED IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED IS_DATASOURCE_MIGRATED + IS_BILLING_V2_ENABLED } type WorkspaceUrls { diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index 3e83953d551..6a72a63d328 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -1145,13 +1145,14 @@ export type BillingUsageType = 'METERED' | 'LICENSED' /** The different billing products available */ -export type BillingProductKey = 'BASE_PRODUCT' | 'WORKFLOW_NODE_EXECUTION' +export type BillingProductKey = 'BASE_PRODUCT' | 'RESOURCE_CREDIT' | 'WORKFLOW_NODE_EXECUTION' export interface BillingPriceLicensed { recurringInterval: SubscriptionInterval unitAmount: Scalars['Float'] stripePriceId: Scalars['String'] priceUsageType: BillingUsageType + creditAmount?: Scalars['Float'] __typename: 'BillingPriceLicensed' } @@ -1244,7 +1245,8 @@ export interface BillingMeteredProductUsage { export interface BillingPlan { planKey: BillingPlanKey - licensedProducts: BillingLicensedProduct[] + baseProducts: BillingLicensedProduct[] + resourceCreditProducts: BillingLicensedProduct[] meteredProducts: BillingMeteredProduct[] __typename: 'BillingPlan' } @@ -1386,7 +1388,7 @@ export interface FeatureFlag { __typename: 'FeatureFlag' } -export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_DATASOURCE_MIGRATED' +export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_DATASOURCE_MIGRATED' | 'IS_BILLING_V2_ENABLED' export interface WorkspaceUrls { customUrl?: Scalars['String'] @@ -4079,6 +4081,7 @@ export interface BillingPriceLicensedGenqlSelection{ unitAmount?: boolean | number stripePriceId?: boolean | number priceUsageType?: boolean | number + creditAmount?: boolean | number __typename?: boolean | number __scalar?: boolean | number } @@ -4177,7 +4180,8 @@ export interface BillingMeteredProductUsageGenqlSelection{ export interface BillingPlanGenqlSelection{ planKey?: boolean | number - licensedProducts?: BillingLicensedProductGenqlSelection + baseProducts?: BillingLicensedProductGenqlSelection + resourceCreditProducts?: BillingLicensedProductGenqlSelection meteredProducts?: BillingMeteredProductGenqlSelection __typename?: boolean | number __scalar?: boolean | number @@ -8629,6 +8633,7 @@ export const enumBillingUsageType = { export const enumBillingProductKey = { BASE_PRODUCT: 'BASE_PRODUCT' as const, + RESOURCE_CREDIT: 'RESOURCE_CREDIT' as const, WORKFLOW_NODE_EXECUTION: 'WORKFLOW_NODE_EXECUTION' as const } @@ -8690,7 +8695,8 @@ export const enumFeatureFlagKey = { IS_CONNECTED_ACCOUNT_MIGRATED: 'IS_CONNECTED_ACCOUNT_MIGRATED' as const, IS_RICH_TEXT_V1_MIGRATED: 'IS_RICH_TEXT_V1_MIGRATED' as const, IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED: 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' as const, - IS_DATASOURCE_MIGRATED: 'IS_DATASOURCE_MIGRATED' as const + IS_DATASOURCE_MIGRATED: 'IS_DATASOURCE_MIGRATED' as const, + IS_BILLING_V2_ENABLED: 'IS_BILLING_V2_ENABLED' as const } export const enumIdentityProviderType = { diff --git a/packages/twenty-client-sdk/src/metadata/generated/types.ts b/packages/twenty-client-sdk/src/metadata/generated/types.ts index 5eed38d2b00..1251f03c64f 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/types.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/types.ts @@ -2956,6 +2956,9 @@ export default { "priceUsageType": [ 136 ], + "creditAmount": [ + 11 + ], "__typename": [ 1 ] @@ -3143,7 +3146,10 @@ export default { "planKey": [ 135 ], - "licensedProducts": [ + "baseProducts": [ + 143 + ], + "resourceCreditProducts": [ 143 ], "meteredProducts": [ diff --git a/packages/twenty-front/src/generated-admin/graphql.ts b/packages/twenty-front/src/generated-admin/graphql.ts index 19fb87c0622..ff6de35d187 100644 --- a/packages/twenty-front/src/generated-admin/graphql.ts +++ b/packages/twenty-front/src/generated-admin/graphql.ts @@ -270,6 +270,7 @@ export type FeatureFlag = { }; export enum FeatureFlagKey { + IS_BILLING_V2_ENABLED = 'IS_BILLING_V2_ENABLED', IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED', IS_CONNECTED_ACCOUNT_MIGRATED = 'IS_CONNECTED_ACCOUNT_MIGRATED', IS_DATASOURCE_MIGRATED = 'IS_DATASOURCE_MIGRATED', diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 7bedf272ecc..39e8a9291ab 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -594,9 +594,10 @@ export type BillingMeteredProductUsage = { export type BillingPlan = { __typename?: 'BillingPlan'; - licensedProducts: Array; + baseProducts: Array; meteredProducts: Array; planKey: BillingPlanKey; + resourceCreditProducts: Array; }; /** The different billing plans available */ @@ -607,6 +608,7 @@ export enum BillingPlanKey { export type BillingPriceLicensed = { __typename?: 'BillingPriceLicensed'; + creditAmount?: Maybe; priceUsageType: BillingUsageType; recurringInterval: SubscriptionInterval; stripePriceId: Scalars['String']; @@ -646,6 +648,7 @@ export type BillingProductDto = { /** The different billing products available */ export enum BillingProductKey { BASE_PRODUCT = 'BASE_PRODUCT', + RESOURCE_CREDIT = 'RESOURCE_CREDIT', WORKFLOW_NODE_EXECUTION = 'WORKFLOW_NODE_EXECUTION' } @@ -1614,6 +1617,7 @@ export type FeatureFlag = { }; export enum FeatureFlagKey { + IS_BILLING_V2_ENABLED = 'IS_BILLING_V2_ENABLED', IS_COMMAND_MENU_ITEM_ENABLED = 'IS_COMMAND_MENU_ITEM_ENABLED', IS_CONNECTED_ACCOUNT_MIGRATED = 'IS_CONNECTED_ACCOUNT_MIGRATED', IS_DATASOURCE_MIGRATED = 'IS_DATASOURCE_MIGRATED', @@ -6993,7 +6997,7 @@ export type ApplicationConnectionProvidersQueryVariables = Exact<{ export type ApplicationConnectionProvidersQuery = { __typename?: 'Query', applicationConnectionProviders: Array<{ __typename?: 'ApplicationConnectionProvider', id: string, applicationId: string, type: string, name: string, displayName: string, oauth?: { __typename?: 'ApplicationConnectionProviderOAuthConfig', scopes: Array, isClientCredentialsConfigured: boolean } | null }> }; -export type BillingPriceLicensedFragmentFragment = { __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType }; +export type BillingPriceLicensedFragmentFragment = { __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType, creditAmount?: number | null }; export type BillingPriceMeteredFragmentFragment = { __typename?: 'BillingPriceMetered', priceUsageType: BillingUsageType, recurringInterval: SubscriptionInterval, stripePriceId: string, tiers: Array<{ __typename?: 'BillingPriceTier', flatAmount?: number | null, unitAmount?: number | null, upTo?: number | null }> }; @@ -7063,7 +7067,7 @@ export type GetMeteredProductsUsageQuery = { __typename?: 'Query', getMeteredPro export type ListPlansQueryVariables = Exact<{ [key: string]: never; }>; -export type ListPlansQuery = { __typename?: 'Query', listPlans: Array<{ __typename?: 'BillingPlan', planKey: BillingPlanKey, licensedProducts: Array<{ __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }>, meteredProducts: Array<{ __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceMetered', priceUsageType: BillingUsageType, recurringInterval: SubscriptionInterval, stripePriceId: string, tiers: Array<{ __typename?: 'BillingPriceTier', flatAmount?: number | null, unitAmount?: number | null, upTo?: number | null }> }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }> }> }; +export type ListPlansQuery = { __typename?: 'Query', listPlans: Array<{ __typename?: 'BillingPlan', planKey: BillingPlanKey, baseProducts: Array<{ __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType, creditAmount?: number | null }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }>, resourceCreditProducts: Array<{ __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType, creditAmount?: number | null }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }>, meteredProducts: Array<{ __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceMetered', priceUsageType: BillingUsageType, recurringInterval: SubscriptionInterval, stripePriceId: string, tiers: Array<{ __typename?: 'BillingPriceTier', flatAmount?: number | null, unitAmount?: number | null, upTo?: number | null }> }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }> }> }; export type ApiKeyFragmentFragment = { __typename?: 'ApiKey', id: string, name: string, expiresAt: string, revokedAt?: string | null, role: { __typename?: 'Role', id: string, label: string, icon?: string | null } }; @@ -7870,7 +7874,7 @@ export const NavigationMenuItemFieldsFragmentDoc = {"kind":"Document","definitio export const NavigationMenuItemQueryFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"pageLayoutId"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const PublicConnectionParamsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PublicConnectionParams"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PublicConnectionParametersOutput"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"secure"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}}]} as unknown as DocumentNode; export const ApplicationRegistrationFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ApplicationRegistrationFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ApplicationRegistration"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"oAuthClientId"}},{"kind":"Field","name":{"kind":"Name","value":"oAuthRedirectUris"}},{"kind":"Field","name":{"kind":"Name","value":"oAuthScopes"}},{"kind":"Field","name":{"kind":"Name","value":"sourceType"}},{"kind":"Field","name":{"kind":"Name","value":"sourcePackage"}},{"kind":"Field","name":{"kind":"Name","value":"latestAvailableVersion"}},{"kind":"Field","name":{"kind":"Name","value":"isListed"}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"isPreInstalled"}},{"kind":"Field","name":{"kind":"Name","value":"isConfigured"}},{"kind":"Field","name":{"kind":"Name","value":"ownerWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; -export const BillingPriceLicensedFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingPriceLicensedFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingPriceLicensed"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"unitAmount"}},{"kind":"Field","name":{"kind":"Name","value":"recurringInterval"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageType"}}]}}]} as unknown as DocumentNode; +export const BillingPriceLicensedFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingPriceLicensedFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingPriceLicensed"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"unitAmount"}},{"kind":"Field","name":{"kind":"Name","value":"recurringInterval"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageType"}},{"kind":"Field","name":{"kind":"Name","value":"creditAmount"}}]}}]} as unknown as DocumentNode; export const BillingPriceMeteredFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingPriceMeteredFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingPriceMetered"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"priceUsageType"}},{"kind":"Field","name":{"kind":"Name","value":"recurringInterval"}},{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"tiers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"flatAmount"}},{"kind":"Field","name":{"kind":"Name","value":"unitAmount"}},{"kind":"Field","name":{"kind":"Name","value":"upTo"}}]}}]}}]} as unknown as DocumentNode; export const ApiKeyFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ApiKeyFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ApiKey"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}},{"kind":"Field","name":{"kind":"Name","value":"revokedAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}}]}}]}}]} as unknown as DocumentNode; export const WebhookFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WebhookFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Webhook"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"targetUrl"}},{"kind":"Field","name":{"kind":"Name","value":"operations"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"secret"}}]}}]} as unknown as DocumentNode; @@ -8046,7 +8050,7 @@ export const SwitchBillingPlanDocument = {"kind":"Document","definitions":[{"kin export const SwitchSubscriptionIntervalDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SwitchSubscriptionInterval"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"switchSubscriptionInterval"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"currentBillingSubscription"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CurrentBillingSubscriptionFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"billingSubscriptions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingSubscriptionFragment"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingSubscriptionSchedulePhaseItemFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingSubscriptionSchedulePhaseItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"quantity"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingSubscriptionSchedulePhaseFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingSubscriptionSchedulePhase"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"start_date"}},{"kind":"Field","name":{"kind":"Name","value":"end_date"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingSubscriptionSchedulePhaseItemFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CurrentBillingSubscriptionFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingSubscription"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"interval"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"}},{"kind":"Field","name":{"kind":"Name","value":"currentPeriodEnd"}},{"kind":"Field","name":{"kind":"Name","value":"phases"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingSubscriptionSchedulePhaseFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"billingSubscriptionItems"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"hasReachedCurrentPeriodCap"}},{"kind":"Field","name":{"kind":"Name","value":"quantity"}},{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"billingProduct"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productKey"}},{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageBased"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingSubscriptionFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingSubscription"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"}},{"kind":"Field","name":{"kind":"Name","value":"phases"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingSubscriptionSchedulePhaseFragment"}}]}}]}}]} as unknown as DocumentNode; export const BillingPortalSessionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"BillingPortalSession"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"returnUrlPath"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"billingPortalSession"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"returnUrlPath"},"value":{"kind":"Variable","name":{"kind":"Name","value":"returnUrlPath"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]} as unknown as DocumentNode; export const GetMeteredProductsUsageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMeteredProductsUsage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getMeteredProductsUsage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productKey"}},{"kind":"Field","name":{"kind":"Name","value":"usedCredits"}},{"kind":"Field","name":{"kind":"Name","value":"grantedCredits"}},{"kind":"Field","name":{"kind":"Name","value":"rolloverCredits"}},{"kind":"Field","name":{"kind":"Name","value":"totalGrantedCredits"}},{"kind":"Field","name":{"kind":"Name","value":"unitPriceCents"}}]}}]}}]} as unknown as DocumentNode; -export const ListPlansDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"listPlans"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"listPlans"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"licensedProducts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productKey"}},{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageBased"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingLicensedProduct"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"prices"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingPriceLicensedFragment"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"meteredProducts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productKey"}},{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageBased"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingMeteredProduct"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"prices"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingPriceMeteredFragment"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingPriceLicensedFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingPriceLicensed"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"unitAmount"}},{"kind":"Field","name":{"kind":"Name","value":"recurringInterval"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageType"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingPriceMeteredFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingPriceMetered"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"priceUsageType"}},{"kind":"Field","name":{"kind":"Name","value":"recurringInterval"}},{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"tiers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"flatAmount"}},{"kind":"Field","name":{"kind":"Name","value":"unitAmount"}},{"kind":"Field","name":{"kind":"Name","value":"upTo"}}]}}]}}]} as unknown as DocumentNode; +export const ListPlansDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"listPlans"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"listPlans"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"baseProducts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productKey"}},{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageBased"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingLicensedProduct"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"prices"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingPriceLicensedFragment"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"resourceCreditProducts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productKey"}},{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageBased"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingLicensedProduct"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"prices"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingPriceLicensedFragment"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"meteredProducts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"metadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"productKey"}},{"kind":"Field","name":{"kind":"Name","value":"planKey"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageBased"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingMeteredProduct"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"prices"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BillingPriceMeteredFragment"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingPriceLicensedFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingPriceLicensed"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"unitAmount"}},{"kind":"Field","name":{"kind":"Name","value":"recurringInterval"}},{"kind":"Field","name":{"kind":"Name","value":"priceUsageType"}},{"kind":"Field","name":{"kind":"Name","value":"creditAmount"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BillingPriceMeteredFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"BillingPriceMetered"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"priceUsageType"}},{"kind":"Field","name":{"kind":"Name","value":"recurringInterval"}},{"kind":"Field","name":{"kind":"Name","value":"stripePriceId"}},{"kind":"Field","name":{"kind":"Name","value":"tiers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"flatAmount"}},{"kind":"Field","name":{"kind":"Name","value":"unitAmount"}},{"kind":"Field","name":{"kind":"Name","value":"upTo"}}]}}]}}]} as unknown as DocumentNode; export const AssignRoleToApiKeyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AssignRoleToApiKey"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"apiKeyId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"roleId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignRoleToApiKey"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"apiKeyId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"apiKeyId"}}},{"kind":"Argument","name":{"kind":"Name","value":"roleId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"roleId"}}}]}]}}]} as unknown as DocumentNode; export const CreateApiKeyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateApiKey"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateApiKeyInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createApiKey"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ApiKeyFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ApiKeyFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ApiKey"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}},{"kind":"Field","name":{"kind":"Name","value":"revokedAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}}]}}]}}]} as unknown as DocumentNode; export const CreateWebhookDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateWebhook"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateWebhookInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createWebhook"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WebhookFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WebhookFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Webhook"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"targetUrl"}},{"kind":"Field","name":{"kind":"Name","value":"operations"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"secret"}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/ai/components/AIChatNoMoreBillingCreditsBanner.tsx b/packages/twenty-front/src/modules/ai/components/AIChatNoMoreBillingCreditsBanner.tsx index abf02e0c879..3427e9ffe9b 100644 --- a/packages/twenty-front/src/modules/ai/components/AIChatNoMoreBillingCreditsBanner.tsx +++ b/packages/twenty-front/src/modules/ai/components/AIChatNoMoreBillingCreditsBanner.tsx @@ -2,17 +2,20 @@ import { AiChatBanner } from '@/ai/components/AiChatBanner'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { useNumberFormat } from '@/localization/hooks/useNumberFormat'; import { useEndSubscriptionTrialPeriod } from '@/settings/billing/hooks/useEndSubscriptionTrialPeriod'; +import { useGetNextResourceCreditPrice } from '@/settings/billing/hooks/useGetNextResourceCreditPrice'; import { useGetNextMeteredBillingPrice } from '@/settings/billing/hooks/useGetNextMeteredBillingPrice'; import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useModal } from '@/ui/layout/modal/hooks/useModal'; import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus'; import { useMutation } from '@apollo/client/react'; import { t } from '@lingui/core/macro'; import { isDefined } from 'twenty-shared/utils'; import { + FeatureFlagKey, PermissionFlagType, SetMeteredSubscriptionPriceDocument, SubscriptionInterval, @@ -29,7 +32,14 @@ export const AIChatNoMoreBillingCreditsBanner = () => { const { openModal } = useModal(); const { endTrialPeriod, isLoading: isEndTrialLoading } = useEndSubscriptionTrialPeriod(); + + const isV2 = useIsFeatureEnabled(FeatureFlagKey.IS_BILLING_V2_ENABLED); + const nextMeteredBillingPrice = useGetNextMeteredBillingPrice(); + const nextResourceCreditPrice = useGetNextResourceCreditPrice(); + + const nextPrice = isV2 ? nextResourceCreditPrice : nextMeteredBillingPrice; + const { formatNumber } = useNumberFormat(); const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar(); @@ -50,46 +60,65 @@ export const AIChatNoMoreBillingCreditsBanner = () => { const isTrialing = subscriptionStatus === SubscriptionStatus.Trialing; - const nextTierCredits = isDefined(nextMeteredBillingPrice) - ? formatNumber(nextMeteredBillingPrice.tiers[0].upTo, { - abbreviate: true, - decimals: 2, - }) + const nextTierCredits = isDefined(nextPrice) + ? isV2 + ? formatNumber( + (nextPrice as typeof nextResourceCreditPrice)?.creditAmount ?? 0, + { + abbreviate: true, + decimals: 2, + }, + ) + : formatNumber( + (nextPrice as typeof nextMeteredBillingPrice)?.tiers?.[0]?.upTo ?? 0, + { + abbreviate: true, + decimals: 2, + }, + ) : null; - const nextTierPrice = isDefined(nextMeteredBillingPrice) - ? formatNumber(nextMeteredBillingPrice.tiers[0].flatAmount / 100) + const nextTierPrice = isDefined(nextPrice) + ? isV2 + ? formatNumber( + ((nextPrice as typeof nextResourceCreditPrice)?.unitAmount ?? 0) / + 100, + ) + : formatNumber( + ((nextPrice as typeof nextMeteredBillingPrice)?.tiers?.[0] + ?.flatAmount ?? 0) / 100, + ) : null; - const nextTierInterval = isDefined(nextMeteredBillingPrice) - ? nextMeteredBillingPrice.recurringInterval === SubscriptionInterval.Month + const nextTierInterval = isDefined(nextPrice) + ? nextPrice.recurringInterval === SubscriptionInterval.Month ? t`month` : t`year` : null; const message = isTrialing ? t`You've hit your usage limit. Subscribe for more usage.` - : isDefined(nextMeteredBillingPrice) + : isDefined(nextPrice) ? t`You've hit your usage limit. \nUpgrade to ${nextTierCredits} credits for $${nextTierPrice}/${nextTierInterval}.` : t`You've hit your usage limit. \nReach to our support team to upgrade.`; const buttonTitle = isTrialing ? t`Subscribe Now` - : isDefined(nextMeteredBillingPrice) + : isDefined(nextPrice) ? t`Upgrade` : undefined; const handleButtonClick = isTrialing ? () => openModal(AI_CHAT_END_TRIAL_PERIOD_MODAL_ID) - : isDefined(nextMeteredBillingPrice) + : isDefined(nextPrice) ? () => openModal(AI_CHAT_UPGRADE_CREDIT_PLAN_MODAL_ID) : undefined; const handleUpgradeConfirm = async () => { - if (!isDefined(nextMeteredBillingPrice)) return; + if (!isDefined(nextPrice)) return; try { const { data } = await setMeteredSubscriptionPrice({ - variables: { priceId: nextMeteredBillingPrice.stripePriceId }, + variables: { priceId: nextPrice.stripePriceId }, }); if ( isDefined( diff --git a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminWorkspaceBillingContent.tsx b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminWorkspaceBillingContent.tsx index 37e3ad7f9b2..5d4a5706c27 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminWorkspaceBillingContent.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminWorkspaceBillingContent.tsx @@ -38,6 +38,7 @@ import { const STRIPE_DASHBOARD_BASE_URL = 'https://dashboard.stripe.com'; const BASE_PRODUCT_KEY = 'BASE_PRODUCT'; const METERED_PRODUCT_KEY = 'WORKFLOW_NODE_EXECUTION'; +const RESOURCE_CREDIT_KEY = 'RESOURCE_CREDIT'; const EM_DASH = '\u2014'; type SettingsAdminWorkspaceBillingContentProps = { @@ -319,7 +320,8 @@ export const SettingsAdminWorkspaceBillingContent = ({ Icon: item.productKey === BASE_PRODUCT_KEY ? IconUsers - : item.productKey === METERED_PRODUCT_KEY + : item.productKey === METERED_PRODUCT_KEY || + item.productKey === RESOURCE_CREDIT_KEY ? IconCoins : IconBox, label: item.productName || t`Unnamed product`, diff --git a/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingContent.tsx b/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingContent.tsx index 197d0754b06..4a618a921c0 100644 --- a/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingContent.tsx +++ b/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingContent.tsx @@ -4,9 +4,11 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { useRedirect } from '@/domain-manager/hooks/useRedirect'; import { SettingsBillingCreditsSection } from '@/settings/billing/components/SettingsBillingCreditsSection'; import { SettingsBillingSubscriptionInfo } from '@/settings/billing/components/SettingsBillingSubscriptionInfo'; +import { useGetResourceCreditUsage } from '@/settings/billing/hooks/useGetResourceCreditUsage'; import { useGetWorkflowNodeExecutionUsage } from '@/settings/billing/hooks/useGetWorkflowNodeExecutionUsage'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus'; import { useQuery } from '@apollo/client/react'; import { isDefined } from 'twenty-shared/utils'; @@ -15,9 +17,9 @@ import { Button } from 'twenty-ui/input'; import { Section } from 'twenty-ui/layout'; import { BillingPortalSessionDocument, + FeatureFlagKey, SubscriptionStatus, } from '~/generated-metadata/graphql'; - export const SettingsBillingContent = () => { const { t } = useLingui(); @@ -31,8 +33,15 @@ export const SettingsBillingContent = () => { const subscriptionStatus = useSubscriptionStatus(); + const isV2 = useIsFeatureEnabled(FeatureFlagKey.IS_BILLING_V2_ENABLED); + const { isGetMeteredProductsUsageQueryLoaded } = useGetWorkflowNodeExecutionUsage(); + const { isGetResourceCreditUsageQueryLoaded } = useGetResourceCreditUsage(); + + const isUsageQueryLoaded = isV2 + ? isGetResourceCreditUsageQueryLoaded + : isGetMeteredProductsUsageQueryLoaded; const hasNotCanceledCurrentSubscription = isDefined(subscriptionStatus) && @@ -69,7 +78,7 @@ export const SettingsBillingContent = () => { {hasNotCanceledCurrentSubscription && currentWorkspace && currentWorkspace.currentBillingSubscription && - isGetMeteredProductsUsageQueryLoaded && ( + isUsageQueryLoaded && (
@@ -128,20 +143,27 @@ export const SettingsBillingCreditsSection = ({ })} /> )} - - - - + {!isV2 && ( + <> + + + + + + )} )} @@ -170,10 +192,17 @@ export const SettingsBillingCreditsSection = ({
- + {isV2 ? ( + + ) : ( + + )}
); diff --git a/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingSubscriptionInfo.tsx b/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingSubscriptionInfo.tsx index 285fbfa07ce..5bb19072e78 100644 --- a/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingSubscriptionInfo.tsx +++ b/packages/twenty-front/src/modules/settings/billing/components/SettingsBillingSubscriptionInfo.tsx @@ -9,27 +9,31 @@ import { currentWorkspaceState, } from '@/auth/states/currentWorkspaceState'; +import { useNumberFormat } from '@/localization/hooks/useNumberFormat'; import { PlansTags } from '@/settings/billing/components/internal/PlansTags'; import { useBillingWording } from '@/settings/billing/hooks/useBillingWording'; import { useCurrentBillingFlags } from '@/settings/billing/hooks/useCurrentBillingFlags'; import { useCurrentMetered } from '@/settings/billing/hooks/useCurrentMetered'; import { useCurrentPlan } from '@/settings/billing/hooks/useCurrentPlan'; +import { useCurrentResourceCredit } from '@/settings/billing/hooks/useCurrentResourceCredit'; import { useEndSubscriptionTrialPeriod } from '@/settings/billing/hooks/useEndSubscriptionTrialPeriod'; +import { useGetResourceCreditUsage } from '@/settings/billing/hooks/useGetResourceCreditUsage'; import { useGetWorkflowNodeExecutionUsage } from '@/settings/billing/hooks/useGetWorkflowNodeExecutionUsage'; import { useHasNextBillingPhase } from '@/settings/billing/hooks/useHasNextBillingPhase'; import { useNextBillingPhase } from '@/settings/billing/hooks/useNextBillingPhase'; import { useNextBillingSeats } from '@/settings/billing/hooks/useNextBillingSeats'; import { useNextPlan } from '@/settings/billing/hooks/useNextPlan'; import { useSplitPhaseItemsInPrices } from '@/settings/billing/hooks/useSplitPhaseItemsInPrices'; -import { useNumberFormat } from '@/localization/hooks/useNumberFormat'; import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useModal } from '@/ui/layout/modal/hooks/useModal'; +import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus'; +import { useMutation } from '@apollo/client/react'; import { styled } from '@linaria/react'; import { useLingui } from '@lingui/react/macro'; -import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; import { useMemo, useState } from 'react'; import { isDefined } from 'twenty-shared/utils'; import { @@ -46,16 +50,16 @@ import { import { Button } from 'twenty-ui/input'; import { Section } from 'twenty-ui/layout'; import { themeCssVariables } from 'twenty-ui/theme-constants'; -import { useMutation } from '@apollo/client/react'; import { BillingPlanKey, BillingProductKey, - PermissionFlagType, - SubscriptionInterval, - SubscriptionStatus, CancelSwitchBillingIntervalDocument, CancelSwitchBillingPlanDocument, CancelSwitchMeteredPriceDocument, + FeatureFlagKey, + PermissionFlagType, + SubscriptionInterval, + SubscriptionStatus, SwitchBillingPlanDocument, SwitchSubscriptionIntervalDocument, } from '~/generated-metadata/graphql'; @@ -103,11 +107,19 @@ export const SettingsBillingSubscriptionInfo = ({ const { openModal } = useModal(); + const isV2 = useIsFeatureEnabled(FeatureFlagKey.IS_BILLING_V2_ENABLED); + const { refetchMeteredProductsUsage } = useGetWorkflowNodeExecutionUsage(); + const { refetchResourceCreditUsage } = useGetResourceCreditUsage(); + + const refetchUsage = isV2 + ? refetchResourceCreditUsage + : refetchMeteredProductsUsage; const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar(); const { currentMeteredBillingPrice } = useCurrentMetered(); + const { currentResourceCreditBillingPrice } = useCurrentResourceCredit(); const { currentPlan, oppositPlan } = useCurrentPlan(); const { isEnterprisePlan, isYearlyPlan, isMonthlyPlan, isProPlan } = @@ -119,10 +131,25 @@ export const SettingsBillingSubscriptionInfo = ({ const { nextBillingSeats } = useNextBillingSeats(); const { nextBillingPhase } = useNextBillingPhase(); const nextInterval = - splitedPhaseItemsInPrices?.nextLicensedPrice?.recurringInterval; - const nextMeteredBillingPrice = splitedPhaseItemsInPrices.nextMereredPrice; + splitedPhaseItemsInPrices?.nextBasePrice?.recurringInterval; + const nextMeteredBillingPrice = splitedPhaseItemsInPrices.nextMeteredPrice; + const nextResourceCreditPrice = + splitedPhaseItemsInPrices.nextResourceCreditPrice; const subscriptionStatus = useSubscriptionStatus(); + const currentInterval = isV2 + ? currentBillingSubscription.interval + : currentMeteredBillingPrice?.recurringInterval; + + const currentCreditsByPeriod = isV2 + ? (currentResourceCreditBillingPrice?.creditAmount ?? null) + : ((currentMeteredBillingPrice as { tiers?: { upTo: number }[] } | null) + ?.tiers?.[0]?.upTo ?? null); + + const nextCreditsByPeriod = isV2 + ? (nextResourceCreditPrice?.creditAmount ?? null) + : (nextMeteredBillingPrice?.tiers?.[0]?.upTo ?? null); + const { getIntervalLabelAsAdjectiveCapitalize, confirmationModalSwitchToProMessage, @@ -210,7 +237,7 @@ export const SettingsBillingSubscriptionInfo = ({ currentBillingSubscription, billingSubscriptions, }); - refetchMeteredProductsUsage(); + refetchUsage(); }; const switchInterval = async () => { @@ -337,11 +364,15 @@ export const SettingsBillingSubscriptionInfo = ({ } enqueueSuccessSnackBar({ - message: t`Metered tier switching has been cancelled.`, + message: isV2 + ? t`Credit pack switching has been cancelled.` + : t`Metered tier switching has been cancelled.`, }); } catch { enqueueErrorSnackBar({ - message: t`Error while cancelling metered tier switching.`, + message: isV2 + ? t`Error while cancelling credit pack switching.` + : t`Error while cancelling metered tier switching.`, }); } finally { setIsCancellingMeteredSwitch(false); @@ -375,8 +406,7 @@ export const SettingsBillingSubscriptionInfo = ({ label={t`Billing interval`} Icon={IconCalendarEvent} currentValue={getIntervalLabelAsAdjectiveCapitalize( - currentMeteredBillingPrice.recurringInterval === - SubscriptionInterval.Month, + currentInterval === SubscriptionInterval.Month, )} nextValue={ nextInterval @@ -407,13 +437,17 @@ export const SettingsBillingSubscriptionInfo = ({ )} - {nextInterval && - currentMeteredBillingPrice.recurringInterval !== nextInterval && ( -