fix: prevent billingPortal creation if no active subscription (#9701)
Billing portal is created in settings/billing page even if subscription is canceled, causing server internal error. -> Skip back end request Bonus : display settings/billing page with disabled button even if subscription is canceled --------- Co-authored-by: etiennejouan <jouan.etienne@gmail.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -135,22 +135,6 @@ export type BillingSubscription = {
|
|||||||
status: SubscriptionStatus;
|
status: SubscriptionStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BillingSubscriptionFilter = {
|
|
||||||
and?: InputMaybe<Array<BillingSubscriptionFilter>>;
|
|
||||||
id?: InputMaybe<UuidFilterComparison>;
|
|
||||||
or?: InputMaybe<Array<BillingSubscriptionFilter>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingSubscriptionSort = {
|
|
||||||
direction: SortDirection;
|
|
||||||
field: BillingSubscriptionSortFields;
|
|
||||||
nulls?: InputMaybe<SortNulls>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum BillingSubscriptionSortFields {
|
|
||||||
id = 'id'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BooleanFieldComparison = {
|
export type BooleanFieldComparison = {
|
||||||
is?: InputMaybe<Scalars['Boolean']['input']>;
|
is?: InputMaybe<Scalars['Boolean']['input']>;
|
||||||
isNot?: InputMaybe<Scalars['Boolean']['input']>;
|
isNot?: InputMaybe<Scalars['Boolean']['input']>;
|
||||||
@ -1418,18 +1402,6 @@ export type SignUpOutput = {
|
|||||||
workspace: WorkspaceSubdomainAndId;
|
workspace: WorkspaceSubdomainAndId;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Sort Directions */
|
|
||||||
export enum SortDirection {
|
|
||||||
ASC = 'ASC',
|
|
||||||
DESC = 'DESC'
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sort Nulls Options */
|
|
||||||
export enum SortNulls {
|
|
||||||
NULLS_FIRST = 'NULLS_FIRST',
|
|
||||||
NULLS_LAST = 'NULLS_LAST'
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum SubscriptionInterval {
|
export enum SubscriptionInterval {
|
||||||
Day = 'Day',
|
Day = 'Day',
|
||||||
Month = 'Month',
|
Month = 'Month',
|
||||||
@ -1743,9 +1715,7 @@ export type Workspace = {
|
|||||||
__typename?: 'Workspace';
|
__typename?: 'Workspace';
|
||||||
activationStatus: WorkspaceActivationStatus;
|
activationStatus: WorkspaceActivationStatus;
|
||||||
allowImpersonation: Scalars['Boolean']['output'];
|
allowImpersonation: Scalars['Boolean']['output'];
|
||||||
billingCustomers?: Maybe<Array<BillingCustomer>>;
|
billingSubscriptions: Array<BillingSubscription>;
|
||||||
billingEntitlements?: Maybe<Array<BillingEntitlement>>;
|
|
||||||
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
|
||||||
createdAt: Scalars['DateTime']['output'];
|
createdAt: Scalars['DateTime']['output'];
|
||||||
currentBillingSubscription?: Maybe<BillingSubscription>;
|
currentBillingSubscription?: Maybe<BillingSubscription>;
|
||||||
databaseSchema: Scalars['String']['output'];
|
databaseSchema: Scalars['String']['output'];
|
||||||
@ -1768,24 +1738,6 @@ export type Workspace = {
|
|||||||
workspaceMembersCount?: Maybe<Scalars['Float']['output']>;
|
workspaceMembersCount?: Maybe<Scalars['Float']['output']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type WorkspaceBillingCustomersArgs = {
|
|
||||||
filter?: BillingCustomerFilter;
|
|
||||||
sorting?: Array<BillingCustomerSort>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type WorkspaceBillingEntitlementsArgs = {
|
|
||||||
filter?: BillingEntitlementFilter;
|
|
||||||
sorting?: Array<BillingEntitlementSort>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type WorkspaceBillingSubscriptionsArgs = {
|
|
||||||
filter?: BillingSubscriptionFilter;
|
|
||||||
sorting?: Array<BillingSubscriptionSort>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum WorkspaceActivationStatus {
|
export enum WorkspaceActivationStatus {
|
||||||
ACTIVE = 'ACTIVE',
|
ACTIVE = 'ACTIVE',
|
||||||
INACTIVE = 'INACTIVE',
|
INACTIVE = 'INACTIVE',
|
||||||
@ -1864,51 +1816,6 @@ export type WorkspaceSubdomainAndId = {
|
|||||||
subdomain: Scalars['String']['output'];
|
subdomain: Scalars['String']['output'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BillingCustomer = {
|
|
||||||
__typename?: 'billingCustomer';
|
|
||||||
id: Scalars['UUID']['output'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingCustomerFilter = {
|
|
||||||
and?: InputMaybe<Array<BillingCustomerFilter>>;
|
|
||||||
id?: InputMaybe<UuidFilterComparison>;
|
|
||||||
or?: InputMaybe<Array<BillingCustomerFilter>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingCustomerSort = {
|
|
||||||
direction: SortDirection;
|
|
||||||
field: BillingCustomerSortFields;
|
|
||||||
nulls?: InputMaybe<SortNulls>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum BillingCustomerSortFields {
|
|
||||||
id = 'id'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BillingEntitlement = {
|
|
||||||
__typename?: 'billingEntitlement';
|
|
||||||
id: Scalars['UUID']['output'];
|
|
||||||
key: Scalars['String']['output'];
|
|
||||||
value: Scalars['Boolean']['output'];
|
|
||||||
workspaceId: Scalars['String']['output'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingEntitlementFilter = {
|
|
||||||
and?: InputMaybe<Array<BillingEntitlementFilter>>;
|
|
||||||
id?: InputMaybe<UuidFilterComparison>;
|
|
||||||
or?: InputMaybe<Array<BillingEntitlementFilter>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingEntitlementSort = {
|
|
||||||
direction: SortDirection;
|
|
||||||
field: BillingEntitlementSortFields;
|
|
||||||
nulls?: InputMaybe<SortNulls>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum BillingEntitlementSortFields {
|
|
||||||
id = 'id'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Field = {
|
export type Field = {
|
||||||
__typename?: 'field';
|
__typename?: 'field';
|
||||||
createdAt: Scalars['DateTime']['output'];
|
createdAt: Scalars['DateTime']['output'];
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import * as Apollo from '@apollo/client';
|
|
||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
|
import * as Apollo from '@apollo/client';
|
||||||
export type Maybe<T> = T | null;
|
export type Maybe<T> = T | null;
|
||||||
export type InputMaybe<T> = Maybe<T>;
|
export type InputMaybe<T> = Maybe<T>;
|
||||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||||
@ -128,22 +128,6 @@ export type BillingSubscription = {
|
|||||||
status: SubscriptionStatus;
|
status: SubscriptionStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BillingSubscriptionFilter = {
|
|
||||||
and?: InputMaybe<Array<BillingSubscriptionFilter>>;
|
|
||||||
id?: InputMaybe<UuidFilterComparison>;
|
|
||||||
or?: InputMaybe<Array<BillingSubscriptionFilter>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingSubscriptionSort = {
|
|
||||||
direction: SortDirection;
|
|
||||||
field: BillingSubscriptionSortFields;
|
|
||||||
nulls?: InputMaybe<SortNulls>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum BillingSubscriptionSortFields {
|
|
||||||
id = 'id'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BooleanFieldComparison = {
|
export type BooleanFieldComparison = {
|
||||||
is?: InputMaybe<Scalars['Boolean']>;
|
is?: InputMaybe<Scalars['Boolean']>;
|
||||||
isNot?: InputMaybe<Scalars['Boolean']>;
|
isNot?: InputMaybe<Scalars['Boolean']>;
|
||||||
@ -1228,18 +1212,6 @@ export type SignUpOutput = {
|
|||||||
workspace: WorkspaceSubdomainAndId;
|
workspace: WorkspaceSubdomainAndId;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Sort Directions */
|
|
||||||
export enum SortDirection {
|
|
||||||
ASC = 'ASC',
|
|
||||||
DESC = 'DESC'
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sort Nulls Options */
|
|
||||||
export enum SortNulls {
|
|
||||||
NULLS_FIRST = 'NULLS_FIRST',
|
|
||||||
NULLS_LAST = 'NULLS_LAST'
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum SubscriptionInterval {
|
export enum SubscriptionInterval {
|
||||||
Day = 'Day',
|
Day = 'Day',
|
||||||
Month = 'Month',
|
Month = 'Month',
|
||||||
@ -1540,9 +1512,7 @@ export type Workspace = {
|
|||||||
__typename?: 'Workspace';
|
__typename?: 'Workspace';
|
||||||
activationStatus: WorkspaceActivationStatus;
|
activationStatus: WorkspaceActivationStatus;
|
||||||
allowImpersonation: Scalars['Boolean'];
|
allowImpersonation: Scalars['Boolean'];
|
||||||
billingCustomers?: Maybe<Array<BillingCustomer>>;
|
billingSubscriptions: Array<BillingSubscription>;
|
||||||
billingEntitlements?: Maybe<Array<BillingEntitlement>>;
|
|
||||||
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
currentBillingSubscription?: Maybe<BillingSubscription>;
|
currentBillingSubscription?: Maybe<BillingSubscription>;
|
||||||
databaseSchema: Scalars['String'];
|
databaseSchema: Scalars['String'];
|
||||||
@ -1565,24 +1535,6 @@ export type Workspace = {
|
|||||||
workspaceMembersCount?: Maybe<Scalars['Float']>;
|
workspaceMembersCount?: Maybe<Scalars['Float']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type WorkspaceBillingCustomersArgs = {
|
|
||||||
filter?: BillingCustomerFilter;
|
|
||||||
sorting?: Array<BillingCustomerSort>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type WorkspaceBillingEntitlementsArgs = {
|
|
||||||
filter?: BillingEntitlementFilter;
|
|
||||||
sorting?: Array<BillingEntitlementSort>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type WorkspaceBillingSubscriptionsArgs = {
|
|
||||||
filter?: BillingSubscriptionFilter;
|
|
||||||
sorting?: Array<BillingSubscriptionSort>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum WorkspaceActivationStatus {
|
export enum WorkspaceActivationStatus {
|
||||||
ACTIVE = 'ACTIVE',
|
ACTIVE = 'ACTIVE',
|
||||||
INACTIVE = 'INACTIVE',
|
INACTIVE = 'INACTIVE',
|
||||||
@ -1661,51 +1613,6 @@ export type WorkspaceSubdomainAndId = {
|
|||||||
subdomain: Scalars['String'];
|
subdomain: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BillingCustomer = {
|
|
||||||
__typename?: 'billingCustomer';
|
|
||||||
id: Scalars['UUID'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingCustomerFilter = {
|
|
||||||
and?: InputMaybe<Array<BillingCustomerFilter>>;
|
|
||||||
id?: InputMaybe<UuidFilterComparison>;
|
|
||||||
or?: InputMaybe<Array<BillingCustomerFilter>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingCustomerSort = {
|
|
||||||
direction: SortDirection;
|
|
||||||
field: BillingCustomerSortFields;
|
|
||||||
nulls?: InputMaybe<SortNulls>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum BillingCustomerSortFields {
|
|
||||||
id = 'id'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BillingEntitlement = {
|
|
||||||
__typename?: 'billingEntitlement';
|
|
||||||
id: Scalars['UUID'];
|
|
||||||
key: Scalars['String'];
|
|
||||||
value: Scalars['Boolean'];
|
|
||||||
workspaceId: Scalars['String'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingEntitlementFilter = {
|
|
||||||
and?: InputMaybe<Array<BillingEntitlementFilter>>;
|
|
||||||
id?: InputMaybe<UuidFilterComparison>;
|
|
||||||
or?: InputMaybe<Array<BillingEntitlementFilter>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BillingEntitlementSort = {
|
|
||||||
direction: SortDirection;
|
|
||||||
field: BillingEntitlementSortFields;
|
|
||||||
nulls?: InputMaybe<SortNulls>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum BillingEntitlementSortFields {
|
|
||||||
id = 'id'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Field = {
|
export type Field = {
|
||||||
__typename?: 'field';
|
__typename?: 'field';
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
@ -2191,7 +2098,7 @@ export type ListSsoIdentityProvidersByWorkspaceIdQueryVariables = Exact<{ [key:
|
|||||||
|
|
||||||
export type ListSsoIdentityProvidersByWorkspaceIdQuery = { __typename?: 'Query', listSSOIdentityProvidersByWorkspaceId: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> };
|
export type ListSsoIdentityProvidersByWorkspaceIdQuery = { __typename?: 'Query', listSSOIdentityProvidersByWorkspaceId: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> };
|
||||||
|
|
||||||
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null, subdomain: string } | null }> };
|
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null, subdomain: string } | null }> };
|
||||||
|
|
||||||
export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;
|
export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
@ -2208,7 +2115,7 @@ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProf
|
|||||||
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null, subdomain: string } | null }> } };
|
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, analyticsTinybirdJwts?: { __typename?: 'AnalyticsTinybirdJwtMap', getWebhookAnalytics: string, getPageviewsAnalytics: string, getUsersAnalytics: string, getServerlessFunctionDuration: string, getServerlessFunctionSuccessRate: string, getServerlessFunctionErrorCount: string } | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentWorkspace?: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, subdomain: string, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: FeatureFlagKey, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus }> } | null, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null, subdomain: string } | null }> } };
|
||||||
|
|
||||||
export type ActivateWorkflowVersionMutationVariables = Exact<{
|
export type ActivateWorkflowVersionMutationVariables = Exact<{
|
||||||
workflowVersionId: Scalars['String'];
|
workflowVersionId: Scalars['String'];
|
||||||
@ -2504,6 +2411,10 @@ export const UserQueryFragmentFragmentDoc = gql`
|
|||||||
status
|
status
|
||||||
interval
|
interval
|
||||||
}
|
}
|
||||||
|
billingSubscriptions {
|
||||||
|
id
|
||||||
|
status
|
||||||
|
}
|
||||||
workspaceMembersCount
|
workspaceMembersCount
|
||||||
}
|
}
|
||||||
workspaces {
|
workspaces {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export type CurrentWorkspace = Pick<
|
|||||||
| 'allowImpersonation'
|
| 'allowImpersonation'
|
||||||
| 'featureFlags'
|
| 'featureFlags'
|
||||||
| 'activationStatus'
|
| 'activationStatus'
|
||||||
|
| 'billingSubscriptions'
|
||||||
| 'currentBillingSubscription'
|
| 'currentBillingSubscription'
|
||||||
| 'workspaceMembersCount'
|
| 'workspaceMembersCount'
|
||||||
| 'isPublicInviteLinkEnabled'
|
| 'isPublicInviteLinkEnabled'
|
||||||
|
|||||||
@ -160,6 +160,10 @@ export const queries = {
|
|||||||
status
|
status
|
||||||
interval
|
interval
|
||||||
}
|
}
|
||||||
|
billingSubscriptions {
|
||||||
|
id
|
||||||
|
status
|
||||||
|
}
|
||||||
workspaceMembersCount
|
workspaceMembersCount
|
||||||
}
|
}
|
||||||
workspaces {
|
workspaces {
|
||||||
@ -300,6 +304,8 @@ export const responseData = {
|
|||||||
currentBillingSubscription: null,
|
currentBillingSubscription: null,
|
||||||
workspaceMembersCount: 1,
|
workspaceMembersCount: 1,
|
||||||
},
|
},
|
||||||
|
currentBillingSubscription: null,
|
||||||
|
billingSubscriptions: [],
|
||||||
workspaces: [],
|
workspaces: [],
|
||||||
userVars: null,
|
userVars: null,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,7 +4,11 @@ import { Nullable } from 'twenty-ui';
|
|||||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { WorkspaceActivationStatus } from '~/generated/graphql';
|
import {
|
||||||
|
SubscriptionInterval,
|
||||||
|
SubscriptionStatus,
|
||||||
|
WorkspaceActivationStatus,
|
||||||
|
} from '~/generated/graphql';
|
||||||
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
|
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
|
||||||
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
||||||
|
|
||||||
@ -23,6 +27,17 @@ const Wrapper = getJestMetadataAndApolloMocksWrapper({
|
|||||||
isGoogleAuthEnabled: true,
|
isGoogleAuthEnabled: true,
|
||||||
isMicrosoftAuthEnabled: false,
|
isMicrosoftAuthEnabled: false,
|
||||||
isPasswordAuthEnabled: true,
|
isPasswordAuthEnabled: true,
|
||||||
|
currentBillingSubscription: {
|
||||||
|
id: '1',
|
||||||
|
interval: SubscriptionInterval.Month,
|
||||||
|
status: SubscriptionStatus.Active,
|
||||||
|
},
|
||||||
|
billingSubscriptions: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
status: SubscriptionStatus.Active,
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -50,6 +50,10 @@ export const USER_QUERY_FRAGMENT = gql`
|
|||||||
status
|
status
|
||||||
interval
|
interval
|
||||||
}
|
}
|
||||||
|
billingSubscriptions {
|
||||||
|
id
|
||||||
|
status
|
||||||
|
}
|
||||||
workspaceMembersCount
|
workspaceMembersCount
|
||||||
}
|
}
|
||||||
workspaces {
|
workspaces {
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import {
|
|||||||
|
|
||||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage';
|
import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage';
|
||||||
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
|
|
||||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||||
import { SettingsPath } from '@/types/SettingsPath';
|
import { SettingsPath } from '@/types/SettingsPath';
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||||
@ -21,8 +20,8 @@ import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModa
|
|||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||||
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
|
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
|
||||||
import {
|
import {
|
||||||
OnboardingStatus,
|
|
||||||
SubscriptionInterval,
|
SubscriptionInterval,
|
||||||
|
SubscriptionStatus,
|
||||||
useBillingPortalSessionQuery,
|
useBillingPortalSessionQuery,
|
||||||
useUpdateBillingSubscriptionMutation,
|
useUpdateBillingSubscriptionMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
@ -59,9 +58,16 @@ export const SettingsBilling = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { enqueueSnackBar } = useSnackBar();
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
const onboardingStatus = useOnboardingStatus();
|
|
||||||
const subscriptionStatus = useSubscriptionStatus();
|
|
||||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||||
|
const subscriptions = currentWorkspace?.billingSubscriptions;
|
||||||
|
const hasSubscriptions = (subscriptions?.length ?? 0) > 0;
|
||||||
|
|
||||||
|
const subscriptionStatus = useSubscriptionStatus();
|
||||||
|
const hasNotCanceledCurrentSubscription =
|
||||||
|
isDefined(subscriptionStatus) &&
|
||||||
|
subscriptionStatus !== SubscriptionStatus.Canceled;
|
||||||
|
|
||||||
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
||||||
const switchingInfo =
|
const switchingInfo =
|
||||||
currentWorkspace?.currentBillingSubscription?.interval ===
|
currentWorkspace?.currentBillingSubscription?.interval ===
|
||||||
@ -75,18 +81,12 @@ export const SettingsBilling = () => {
|
|||||||
variables: {
|
variables: {
|
||||||
returnUrlPath: '/settings/billing',
|
returnUrlPath: '/settings/billing',
|
||||||
},
|
},
|
||||||
|
skip: !hasSubscriptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
const billingPortalButtonDisabled =
|
const billingPortalButtonDisabled =
|
||||||
loading || !isDefined(data) || !isDefined(data.billingPortalSession.url);
|
loading || !isDefined(data) || !isDefined(data.billingPortalSession.url);
|
||||||
|
|
||||||
const switchIntervalButtonDisabled =
|
|
||||||
onboardingStatus !== OnboardingStatus.COMPLETED;
|
|
||||||
|
|
||||||
const cancelPlanButtonDisabled =
|
|
||||||
billingPortalButtonDisabled ||
|
|
||||||
onboardingStatus !== OnboardingStatus.COMPLETED;
|
|
||||||
|
|
||||||
const openBillingPortal = () => {
|
const openBillingPortal = () => {
|
||||||
if (isDefined(data) && isDefined(data.billingPortalSession.url)) {
|
if (isDefined(data) && isDefined(data.billingPortalSession.url)) {
|
||||||
window.location.replace(data.billingPortalSession.url);
|
window.location.replace(data.billingPortalSession.url);
|
||||||
@ -137,50 +137,46 @@ export const SettingsBilling = () => {
|
|||||||
>
|
>
|
||||||
<SettingsPageContainer>
|
<SettingsPageContainer>
|
||||||
<SettingsBillingCoverImage />
|
<SettingsBillingCoverImage />
|
||||||
{isDefined(subscriptionStatus) && (
|
<Section>
|
||||||
<>
|
<H2Title
|
||||||
<Section>
|
title={t`Manage your subscription`}
|
||||||
<H2Title
|
description={t`Edit payment method, see your invoices and more`}
|
||||||
title={t`Manage your subscription`}
|
/>
|
||||||
description={t`Edit payment method, see your invoices and more`}
|
<Button
|
||||||
/>
|
Icon={IconCreditCard}
|
||||||
<Button
|
title={t`View billing details`}
|
||||||
Icon={IconCreditCard}
|
variant="secondary"
|
||||||
title={t`View billing details`}
|
onClick={openBillingPortal}
|
||||||
variant="secondary"
|
disabled={billingPortalButtonDisabled}
|
||||||
onClick={openBillingPortal}
|
/>
|
||||||
disabled={billingPortalButtonDisabled}
|
</Section>
|
||||||
/>
|
<Section>
|
||||||
</Section>
|
<H2Title
|
||||||
<Section>
|
title={t`Edit billing interval`}
|
||||||
<H2Title
|
description={t`Switch ${from}`}
|
||||||
title={t`Edit billing interval`}
|
/>
|
||||||
description={t`Switch ${from}`}
|
<Button
|
||||||
/>
|
Icon={IconCalendarEvent}
|
||||||
<Button
|
title={t`Switch ${to}`}
|
||||||
Icon={IconCalendarEvent}
|
variant="secondary"
|
||||||
title={t`Switch ${to}`}
|
onClick={openSwitchingIntervalModal}
|
||||||
variant="secondary"
|
disabled={!hasNotCanceledCurrentSubscription}
|
||||||
onClick={openSwitchingIntervalModal}
|
/>
|
||||||
disabled={switchIntervalButtonDisabled}
|
</Section>
|
||||||
/>
|
<Section>
|
||||||
</Section>
|
<H2Title
|
||||||
<Section>
|
title={t`Cancel your subscription`}
|
||||||
<H2Title
|
description={t`Your workspace will be disabled`}
|
||||||
title={t`Cancel your subscription`}
|
/>
|
||||||
description={t`Your workspace will be disabled`}
|
<Button
|
||||||
/>
|
Icon={IconCircleX}
|
||||||
<Button
|
title={t`Cancel Plan`}
|
||||||
Icon={IconCircleX}
|
variant="secondary"
|
||||||
title={t`Cancel Plan`}
|
accent="danger"
|
||||||
variant="secondary"
|
onClick={openBillingPortal}
|
||||||
accent="danger"
|
disabled={!hasNotCanceledCurrentSubscription}
|
||||||
onClick={openBillingPortal}
|
/>
|
||||||
disabled={cancelPlanButtonDisabled}
|
</Section>
|
||||||
/>
|
|
||||||
</Section>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</SettingsPageContainer>
|
</SettingsPageContainer>
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
isOpen={isSwitchingIntervalModalOpen}
|
isOpen={isSwitchingIntervalModalOpen}
|
||||||
|
|||||||
@ -73,6 +73,13 @@ export const mockCurrentWorkspace: Workspace = {
|
|||||||
interval: SubscriptionInterval.Month,
|
interval: SubscriptionInterval.Month,
|
||||||
status: SubscriptionStatus.Active,
|
status: SubscriptionStatus.Active,
|
||||||
},
|
},
|
||||||
|
billingSubscriptions: [
|
||||||
|
{
|
||||||
|
__typename: 'BillingSubscription',
|
||||||
|
id: '7efbc3f7-6e5e-4128-957e-8d86808cdf6a',
|
||||||
|
status: SubscriptionStatus.Active,
|
||||||
|
},
|
||||||
|
],
|
||||||
workspaceMembersCount: 1,
|
workspaceMembersCount: 1,
|
||||||
databaseSchema: '',
|
databaseSchema: '',
|
||||||
databaseUrl: '',
|
databaseUrl: '',
|
||||||
|
|||||||
@ -79,18 +79,16 @@ export class BillingPortalWorkspaceService {
|
|||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
returnUrlPath?: string,
|
returnUrlPath?: string,
|
||||||
) {
|
) {
|
||||||
const currentSubscription =
|
const lastSubscription = await this.billingSubscriptionRepository.findOne({
|
||||||
await this.billingSubscriptionService.getCurrentBillingSubscriptionOrThrow(
|
where: { workspaceId: workspace.id },
|
||||||
{
|
order: { createdAt: 'DESC' },
|
||||||
workspaceId: workspace.id,
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!currentSubscription) {
|
if (!lastSubscription) {
|
||||||
throw new Error('Error: missing subscription');
|
throw new Error('Error: missing subscription');
|
||||||
}
|
}
|
||||||
|
|
||||||
const stripeCustomerId = currentSubscription.stripeCustomerId;
|
const stripeCustomerId = lastSubscription.stripeCustomerId;
|
||||||
|
|
||||||
if (!stripeCustomerId) {
|
if (!stripeCustomerId) {
|
||||||
throw new Error('Error: missing stripeCustomerId');
|
throw new Error('Error: missing stripeCustomerId');
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||||
|
|
||||||
import { IDField, UnPagedRelation } from '@ptc-org/nestjs-query-graphql';
|
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||||
import { WorkspaceActivationStatus } from 'twenty-shared';
|
import { WorkspaceActivationStatus } from 'twenty-shared';
|
||||||
import {
|
import {
|
||||||
Column,
|
Column,
|
||||||
@ -15,9 +15,6 @@ import {
|
|||||||
|
|
||||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||||
import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity';
|
import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||||
import { BillingCustomer } from 'src/engine/core-modules/billing/entities/billing-customer.entity';
|
|
||||||
import { BillingEntitlement } from 'src/engine/core-modules/billing/entities/billing-entitlement.entity';
|
|
||||||
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
|
|
||||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||||
import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity';
|
import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity';
|
||||||
import { PostgresCredentials } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.entity';
|
import { PostgresCredentials } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.entity';
|
||||||
@ -30,15 +27,6 @@ registerEnumType(WorkspaceActivationStatus, {
|
|||||||
|
|
||||||
@Entity({ name: 'workspace', schema: 'core' })
|
@Entity({ name: 'workspace', schema: 'core' })
|
||||||
@ObjectType('Workspace')
|
@ObjectType('Workspace')
|
||||||
@UnPagedRelation('billingSubscriptions', () => BillingSubscription, {
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
@UnPagedRelation('billingEntitlements', () => BillingEntitlement, {
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
@UnPagedRelation('billingCustomers', () => BillingCustomer, {
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
export class Workspace {
|
export class Workspace {
|
||||||
@IDField(() => UUIDScalarType)
|
@IDField(() => UUIDScalarType)
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql';
|
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql';
|
||||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||||
|
|
||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||||
|
import { TokenModule } from 'src/engine/core-modules/auth/token/token.module';
|
||||||
import { BillingModule } from 'src/engine/core-modules/billing/billing.module';
|
import { BillingModule } from 'src/engine/core-modules/billing/billing.module';
|
||||||
|
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
|
||||||
|
import { DomainManagerModule } from 'src/engine/core-modules/domain-manager/domain-manager.module';
|
||||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||||
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
|
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
|
||||||
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||||
@ -17,8 +21,6 @@ import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.r
|
|||||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||||
import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module';
|
import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module';
|
||||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||||
import { DomainManagerModule } from 'src/engine/core-modules/domain-manager/domain-manager.module';
|
|
||||||
import { TokenModule } from 'src/engine/core-modules/auth/token/token.module';
|
|
||||||
|
|
||||||
import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts';
|
import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts';
|
||||||
import { Workspace } from './workspace.entity';
|
import { Workspace } from './workspace.entity';
|
||||||
@ -28,6 +30,7 @@ import { WorkspaceService } from './services/workspace.service';
|
|||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TypeORMModule,
|
TypeORMModule,
|
||||||
|
TypeOrmModule.forFeature([BillingSubscription], 'core'),
|
||||||
NestjsQueryGraphQLModule.forFeature({
|
NestjsQueryGraphQLModule.forFeature({
|
||||||
imports: [
|
imports: [
|
||||||
DomainManagerModule,
|
DomainManagerModule,
|
||||||
|
|||||||
@ -7,8 +7,10 @@ import {
|
|||||||
ResolveField,
|
ResolveField,
|
||||||
Resolver,
|
Resolver,
|
||||||
} from '@nestjs/graphql';
|
} from '@nestjs/graphql';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { FileUpload, GraphQLUpload } from 'graphql-upload';
|
import { FileUpload, GraphQLUpload } from 'graphql-upload';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
|
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
|
||||||
|
|
||||||
@ -63,6 +65,8 @@ export class WorkspaceResolver {
|
|||||||
private readonly fileService: FileService,
|
private readonly fileService: FileService,
|
||||||
private readonly billingSubscriptionService: BillingSubscriptionService,
|
private readonly billingSubscriptionService: BillingSubscriptionService,
|
||||||
private readonly featureFlagService: FeatureFlagService,
|
private readonly featureFlagService: FeatureFlagService,
|
||||||
|
@InjectRepository(BillingSubscription, 'core')
|
||||||
|
private readonly billingSubscriptionRepository: Repository<BillingSubscription>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Query(() => Workspace)
|
@Query(() => Workspace)
|
||||||
@ -159,6 +163,19 @@ export class WorkspaceResolver {
|
|||||||
return this.workspaceService.deleteWorkspace(id);
|
return this.workspaceService.deleteWorkspace(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ResolveField(() => [BillingSubscription])
|
||||||
|
async billingSubscriptions(
|
||||||
|
@Parent() workspace: Workspace,
|
||||||
|
): Promise<BillingSubscription[] | undefined> {
|
||||||
|
try {
|
||||||
|
return this.billingSubscriptionRepository.find({
|
||||||
|
where: { workspaceId: workspace.id },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
workspaceGraphqlApiExceptionHandler(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ResolveField(() => BillingSubscription, { nullable: true })
|
@ResolveField(() => BillingSubscription, { nullable: true })
|
||||||
async currentBillingSubscription(
|
async currentBillingSubscription(
|
||||||
@Parent() workspace: Workspace,
|
@Parent() workspace: Workspace,
|
||||||
|
|||||||
Reference in New Issue
Block a user