feat(gatekeeper): intoduce the enterprise plan (#4882)
* feat(gatekeeper): intoduce the enterprise plan * chore(server): remove more "magic strings" * test(shared): fix plan tests with enterprise case * Small change to format plan name --------- Co-authored-by: Mike Tasset <mike.tasset@gmail.com>
This commit is contained in:
@@ -26,7 +26,8 @@ export const formatName = (plan?: MaybeNullOrUndefined<WorkspacePlans>) => {
|
||||
[WorkspacePlans.TeamUnlimitedInvoiced]: 'Starter (Invoiced)',
|
||||
[WorkspacePlans.Pro]: 'Business',
|
||||
[WorkspacePlans.ProUnlimited]: 'Business',
|
||||
[WorkspacePlans.ProUnlimitedInvoiced]: 'Business (Invoiced)'
|
||||
[WorkspacePlans.ProUnlimitedInvoiced]: 'Business (Invoiced)',
|
||||
[WorkspacePlans.Enterprise]: 'Enterprise'
|
||||
}
|
||||
return formattedPlanNames[plan]
|
||||
}
|
||||
|
||||
@@ -4931,6 +4931,7 @@ export type WorkspacePlanUsage = {
|
||||
|
||||
export const WorkspacePlans = {
|
||||
Academia: 'academia',
|
||||
Enterprise: 'enterprise',
|
||||
Free: 'free',
|
||||
Pro: 'pro',
|
||||
ProUnlimited: 'proUnlimited',
|
||||
|
||||
@@ -64,6 +64,7 @@ enum WorkspacePlans {
|
||||
pro
|
||||
proUnlimited
|
||||
proUnlimitedInvoiced
|
||||
enterprise
|
||||
}
|
||||
|
||||
enum WorkspacePlanStatuses {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
upsertWorkspacePlanFactory
|
||||
} from '@/modules/gatekeeper/repositories/billing'
|
||||
import { WorkspaceNotFoundError } from '@/modules/workspaces/errors/workspace'
|
||||
import { PaidWorkspacePlans, PaidWorkspacePlanStatuses } from '@speckle/shared'
|
||||
import { WorkspacePlans, WorkspacePlanStatuses } from '@speckle/shared'
|
||||
import { getEventBus } from '@/modules/shared/services/eventBus'
|
||||
import { updateWorkspacePlanFactory } from '@/modules/gatekeeper/services/workspacePlans'
|
||||
|
||||
@@ -18,8 +18,9 @@ const command: CommandModule<
|
||||
unknown,
|
||||
{
|
||||
workspaceSlugOrId: string
|
||||
status: PaidWorkspacePlanStatuses
|
||||
plan: PaidWorkspacePlans
|
||||
// you need to know what you are doing, status and plan pairing validity is not ensured here
|
||||
status: WorkspacePlanStatuses
|
||||
plan: WorkspacePlans
|
||||
}
|
||||
> = {
|
||||
command: 'set-plan <workspaceSlugOrId> [plan] [status]',
|
||||
@@ -32,8 +33,8 @@ const command: CommandModule<
|
||||
plan: {
|
||||
describe: 'Plan to set the status for',
|
||||
type: 'string',
|
||||
default: PaidWorkspacePlans.Team,
|
||||
choices: [PaidWorkspacePlans.Team, PaidWorkspacePlans.Pro]
|
||||
default: WorkspacePlans.Team,
|
||||
choices: Object.values(WorkspacePlans)
|
||||
},
|
||||
status: {
|
||||
describe: 'Status to set for the workspace plan',
|
||||
|
||||
@@ -4954,6 +4954,7 @@ export type WorkspacePlanUsage = {
|
||||
|
||||
export const WorkspacePlans = {
|
||||
Academia: 'academia',
|
||||
Enterprise: 'enterprise',
|
||||
Free: 'free',
|
||||
Pro: 'pro',
|
||||
ProUnlimited: 'proUnlimited',
|
||||
|
||||
@@ -4934,6 +4934,7 @@ export type WorkspacePlanUsage = {
|
||||
|
||||
export const WorkspacePlans = {
|
||||
Academia: 'academia',
|
||||
Enterprise: 'enterprise',
|
||||
Free: 'free',
|
||||
Pro: 'pro',
|
||||
ProUnlimited: 'proUnlimited',
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { getFeatureFlags, getFrontendOrigin } from '@/modules/shared/helpers/envHelper'
|
||||
import type { Resolvers } from '@/modules/core/graph/generated/graphql'
|
||||
import { authorizeResolver } from '@/modules/shared'
|
||||
import { Roles, throwUncoveredError, WorkspacePlanFeatures } from '@speckle/shared'
|
||||
import {
|
||||
Roles,
|
||||
throwUncoveredError,
|
||||
WorkspacePlanFeatures,
|
||||
WorkspacePlans
|
||||
} from '@speckle/shared'
|
||||
import {
|
||||
getWorkspaceFactory,
|
||||
getWorkspaceRoleForUserFactory,
|
||||
@@ -71,19 +76,20 @@ export = FF_GATEKEEPER_MODULE_ENABLED
|
||||
if (!workspacePlan) return null
|
||||
let paymentMethod: WorkspacePaymentMethod
|
||||
switch (workspacePlan.name) {
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
paymentMethod = WorkspacePaymentMethod.Billing
|
||||
break
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case 'free':
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.Free:
|
||||
paymentMethod = WorkspacePaymentMethod.Unpaid
|
||||
break
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.Enterprise:
|
||||
paymentMethod = WorkspacePaymentMethod.Invoice
|
||||
break
|
||||
default:
|
||||
@@ -248,17 +254,18 @@ export = FF_GATEKEEPER_MODULE_ENABLED
|
||||
if (subscription) {
|
||||
let purchased = 0
|
||||
switch (workspacePlan.name) {
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case 'free':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.Enterprise:
|
||||
// not stripe paid plans and old plans do not have seats available
|
||||
break
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
purchased = getTotalSeatsCountByPlanFactory({
|
||||
getWorkspacePlanProductId
|
||||
})({
|
||||
|
||||
@@ -19,7 +19,8 @@ import {
|
||||
import {
|
||||
PaidWorkspacePlans,
|
||||
PaidWorkspacePlanStatuses,
|
||||
throwUncoveredError
|
||||
throwUncoveredError,
|
||||
WorkspacePlans
|
||||
} from '@speckle/shared'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { CountSeatsByTypeInWorkspace } from '@/modules/gatekeeper/domain/operations'
|
||||
@@ -78,16 +79,17 @@ export const handleSubscriptionUpdateFactory =
|
||||
|
||||
if (status) {
|
||||
switch (workspacePlan.name) {
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
break
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'free':
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.Enterprise:
|
||||
throw new WorkspacePlanMismatchError()
|
||||
default:
|
||||
throwUncoveredError(workspacePlan)
|
||||
@@ -146,21 +148,22 @@ export const addWorkspaceSubscriptionSeatIfNeededFactory =
|
||||
// if (!workspaceSubscription) throw new WorkspaceSubscriptionNotFoundError()
|
||||
|
||||
switch (workspacePlan.name) {
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
// If viewer seat type, we don't need to do anything
|
||||
if (seatType === WorkspaceSeatType.Viewer) {
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'free':
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.Enterprise:
|
||||
throw new WorkspacePlanMismatchError()
|
||||
default:
|
||||
throwUncoveredError(workspacePlan)
|
||||
|
||||
+11
-10
@@ -15,7 +15,7 @@ import {
|
||||
} from '@/modules/gatekeeper/errors/billing'
|
||||
import { mutateSubscriptionDataWithNewValidSeatNumbers } from '@/modules/gatekeeper/services/subscriptions/mutateSubscriptionDataWithNewValidSeatNumbers'
|
||||
import { Logger } from '@/observability/logging'
|
||||
import { throwUncoveredError } from '@speckle/shared'
|
||||
import { throwUncoveredError, WorkspacePlans } from '@speckle/shared'
|
||||
import { cloneDeep, isEqual } from 'lodash'
|
||||
|
||||
type DownscaleWorkspaceSubscription = (args: {
|
||||
@@ -41,16 +41,17 @@ export const downscaleWorkspaceSubscriptionFactory =
|
||||
if (!workspacePlan) throw new WorkspacePlanNotFoundError()
|
||||
|
||||
switch (workspacePlan.name) {
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
break
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'free':
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.Enterprise:
|
||||
case WorkspacePlans.Unlimited:
|
||||
throw new WorkspacePlanMismatchError()
|
||||
default:
|
||||
throwUncoveredError(workspacePlan)
|
||||
|
||||
+12
-10
@@ -27,7 +27,8 @@ import { EventBusEmit } from '@/modules/shared/services/eventBus'
|
||||
import {
|
||||
PaidWorkspacePlans,
|
||||
throwUncoveredError,
|
||||
WorkspacePlanBillingIntervals
|
||||
WorkspacePlanBillingIntervals,
|
||||
WorkspacePlans
|
||||
} from '@speckle/shared'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
@@ -68,16 +69,17 @@ export const upgradeWorkspaceSubscriptionFactory =
|
||||
if (!workspacePlan) throw new WorkspacePlanNotFoundError()
|
||||
|
||||
switch (workspacePlan.name) {
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'free': // Upgrade from free is handled through startCheckout since it is from free to paid
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.Enterprise:
|
||||
case WorkspacePlans.Free: // Upgrade from free is handled through startCheckout since it is from free to paid
|
||||
throw new WorkspaceNotPaidPlanError()
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
break
|
||||
default:
|
||||
throwUncoveredError(workspacePlan)
|
||||
|
||||
@@ -9,7 +9,8 @@ const WorkspacePlansUpgradeMapping: Record<WorkspacePlans, WorkspacePlans[]> = {
|
||||
teamUnlimitedInvoiced: [],
|
||||
pro: ['pro', 'proUnlimited'],
|
||||
proUnlimited: ['proUnlimited'],
|
||||
proUnlimitedInvoiced: []
|
||||
proUnlimitedInvoiced: [],
|
||||
enterprise: []
|
||||
}
|
||||
|
||||
export const isUpgradeWorkspacePlanValid = ({
|
||||
|
||||
@@ -6,7 +6,7 @@ import { InvalidWorkspacePlanStatus } from '@/modules/gatekeeper/errors/billing'
|
||||
import { EventBusEmit } from '@/modules/shared/services/eventBus'
|
||||
import { GetWorkspace } from '@/modules/workspaces/domain/operations'
|
||||
import { WorkspaceNotFoundError } from '@/modules/workspaces/errors/workspace'
|
||||
import { throwUncoveredError, WorkspacePlan } from '@speckle/shared'
|
||||
import { throwUncoveredError, WorkspacePlan, WorkspacePlans } from '@speckle/shared'
|
||||
|
||||
export const updateWorkspacePlanFactory =
|
||||
({
|
||||
@@ -35,10 +35,10 @@ export const updateWorkspacePlanFactory =
|
||||
const createdAt = new Date()
|
||||
const updatedAt = new Date()
|
||||
switch (name) {
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
switch (status) {
|
||||
case 'valid':
|
||||
case 'cancelationScheduled':
|
||||
@@ -53,11 +53,12 @@ export const updateWorkspacePlanFactory =
|
||||
}
|
||||
break
|
||||
|
||||
case 'free':
|
||||
case 'academia':
|
||||
case 'unlimited':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Enterprise:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
switch (status) {
|
||||
case 'valid':
|
||||
await upsertWorkspacePlan({
|
||||
|
||||
@@ -116,6 +116,7 @@ import {
|
||||
} from '@/modules/workspaces/services/retrieval'
|
||||
import {
|
||||
Roles,
|
||||
WorkspacePlans,
|
||||
WorkspaceRoles,
|
||||
removeNullOrUndefinedKeys,
|
||||
throwUncoveredError
|
||||
@@ -707,10 +708,10 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
const workspacePlan = await getWorkspacePlanFactory({ db })({ workspaceId })
|
||||
if (workspacePlan) {
|
||||
switch (workspacePlan.name) {
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
switch (workspacePlan.status) {
|
||||
case 'cancelationScheduled':
|
||||
case 'valid':
|
||||
@@ -721,11 +722,12 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
default:
|
||||
throwUncoveredError(workspacePlan)
|
||||
}
|
||||
case 'free':
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.Enterprise:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
break
|
||||
default:
|
||||
throwUncoveredError(workspacePlan)
|
||||
|
||||
@@ -4935,6 +4935,7 @@ export type WorkspacePlanUsage = {
|
||||
|
||||
export const WorkspacePlans = {
|
||||
Academia: 'academia',
|
||||
Enterprise: 'enterprise',
|
||||
Free: 'free',
|
||||
Pro: 'pro',
|
||||
ProUnlimited: 'proUnlimited',
|
||||
|
||||
@@ -148,6 +148,17 @@ export const WorkspacePaidPlanConfigs: {
|
||||
export const WorkspaceUnpaidPlanConfigs: {
|
||||
[plan in UnpaidWorkspacePlans]: WorkspacePlanConfig<plan>
|
||||
} = {
|
||||
[UnpaidWorkspacePlans.Enterprise]: {
|
||||
plan: UnpaidWorkspacePlans.Enterprise,
|
||||
features: [
|
||||
...baseFeatures,
|
||||
WorkspacePlanFeatures.DomainSecurity,
|
||||
WorkspacePlanFeatures.SSO,
|
||||
WorkspacePlanFeatures.CustomDataRegion,
|
||||
WorkspacePlanFeatures.HideSpeckleBranding
|
||||
],
|
||||
limits: unlimited
|
||||
},
|
||||
[UnpaidWorkspacePlans.Unlimited]: {
|
||||
plan: UnpaidWorkspacePlans.Unlimited,
|
||||
features: [
|
||||
|
||||
@@ -18,7 +18,8 @@ describe('plan helpers', () => {
|
||||
proUnlimitedInvoiced: false,
|
||||
team: false,
|
||||
teamUnlimited: true,
|
||||
teamUnlimitedInvoiced: false
|
||||
teamUnlimitedInvoiced: false,
|
||||
enterprise: false
|
||||
}
|
||||
it.each(Object.entries(planCases))(
|
||||
'plan %s include the paid unlimited projects addon -> %s',
|
||||
@@ -41,7 +42,8 @@ describe('plan helpers', () => {
|
||||
proUnlimitedInvoiced: false,
|
||||
team: true,
|
||||
teamUnlimited: true,
|
||||
teamUnlimitedInvoiced: false
|
||||
teamUnlimitedInvoiced: false,
|
||||
enterprise: false
|
||||
}
|
||||
it.each(Object.entries(planCases))(
|
||||
'is plan %s available self served -> %s',
|
||||
|
||||
@@ -13,6 +13,7 @@ export type PaidWorkspacePlans =
|
||||
export const UnpaidWorkspacePlans = <const>{
|
||||
TeamUnlimitedInvoiced: 'teamUnlimitedInvoiced',
|
||||
ProUnlimitedInvoiced: 'proUnlimitedInvoiced',
|
||||
Enterprise: 'enterprise',
|
||||
Unlimited: 'unlimited',
|
||||
Academia: 'academia',
|
||||
Free: 'free'
|
||||
@@ -32,16 +33,17 @@ export const doesPlanIncludeUnlimitedProjectsAddon = (
|
||||
plan: WorkspacePlans
|
||||
): boolean => {
|
||||
switch (plan) {
|
||||
case 'teamUnlimited':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
return true
|
||||
case 'free':
|
||||
case 'team':
|
||||
case 'pro':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.Enterprise:
|
||||
return false
|
||||
|
||||
default:
|
||||
@@ -51,16 +53,17 @@ export const doesPlanIncludeUnlimitedProjectsAddon = (
|
||||
|
||||
export const isSelfServeAvailablePlan = (plan: WorkspacePlans): boolean => {
|
||||
switch (plan) {
|
||||
case 'free':
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
return true
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.Enterprise:
|
||||
return false
|
||||
|
||||
default:
|
||||
@@ -70,16 +73,17 @@ export const isSelfServeAvailablePlan = (plan: WorkspacePlans): boolean => {
|
||||
|
||||
export const isPaidPlan = (plan: WorkspacePlans): boolean => {
|
||||
switch (plan) {
|
||||
case 'team':
|
||||
case 'teamUnlimited':
|
||||
case 'pro':
|
||||
case 'proUnlimited':
|
||||
case WorkspacePlans.Team:
|
||||
case WorkspacePlans.TeamUnlimited:
|
||||
case WorkspacePlans.Pro:
|
||||
case WorkspacePlans.ProUnlimited:
|
||||
return true
|
||||
case 'free':
|
||||
case 'teamUnlimitedInvoiced':
|
||||
case 'proUnlimitedInvoiced':
|
||||
case 'unlimited':
|
||||
case 'academia':
|
||||
case WorkspacePlans.Free:
|
||||
case WorkspacePlans.TeamUnlimitedInvoiced:
|
||||
case WorkspacePlans.ProUnlimitedInvoiced:
|
||||
case WorkspacePlans.Unlimited:
|
||||
case WorkspacePlans.Academia:
|
||||
case WorkspacePlans.Enterprise:
|
||||
return false
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user