From 7b295ba408bbfc5750954557b499a141ac13e5ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Jedlicska?= <57442769+gjedlicska@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:14:33 +0100 Subject: [PATCH] gergo/web 2428 academia should be free business (#3842) * feat(server): workspace shoul equal unpaid business * feat(server): add free workspace plans * feat(gatekeeper): rename plans to invoiced * chore(gatekeeper): regen gql * feat(gatekeeper): calculate workspace plan payment method * fix(fe2): add missing workspace plans --- .../workspaces/billing/PricingTable/Plan.vue | 5 +++- .../lib/common/generated/gql/graphql.ts | 3 ++ .../gatekeeper/typedefs/gatekeeper.graphql | 7 +++++ .../modules/core/graph/generated/graphql.ts | 9 ++++++ .../graph/generated/graphql.ts | 7 +++++ .../gatekeeper/graph/resolvers/index.ts | 28 +++++++++++++++++-- .../server/test/graphql/generated/graphql.ts | 7 +++++ 7 files changed, 63 insertions(+), 3 deletions(-) diff --git a/packages/frontend-2/components/settings/workspaces/billing/PricingTable/Plan.vue b/packages/frontend-2/components/settings/workspaces/billing/PricingTable/Plan.vue index 035464a648..3e264fa6bd 100644 --- a/packages/frontend-2/components/settings/workspaces/billing/PricingTable/Plan.vue +++ b/packages/frontend-2/components/settings/workspaces/billing/PricingTable/Plan.vue @@ -144,7 +144,10 @@ const canUpgradeToPlan = computed(() => { [WorkspacePlans.Plus]: [WorkspacePlans.Business], [WorkspacePlans.Business]: [], [WorkspacePlans.Academia]: [], - [WorkspacePlans.Unlimited]: [] + [WorkspacePlans.Unlimited]: [], + [WorkspacePlans.StarterInvoiced]: [], + [WorkspacePlans.PlusInvoiced]: [], + [WorkspacePlans.BusinessInvoiced]: [] } return allowedUpgrades[props.currentPlan.name].includes(props.plan.name) diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index a12306758e..37a97f2ee6 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -4481,8 +4481,11 @@ export enum WorkspacePlanStatuses { export enum WorkspacePlans { Academia = 'academia', Business = 'business', + BusinessInvoiced = 'businessInvoiced', Plus = 'plus', + PlusInvoiced = 'plusInvoiced', Starter = 'starter', + StarterInvoiced = 'starterInvoiced', Unlimited = 'unlimited' } diff --git a/packages/server/assets/gatekeeper/typedefs/gatekeeper.graphql b/packages/server/assets/gatekeeper/typedefs/gatekeeper.graphql index ff89c387ae..a5cc0a8b56 100644 --- a/packages/server/assets/gatekeeper/typedefs/gatekeeper.graphql +++ b/packages/server/assets/gatekeeper/typedefs/gatekeeper.graphql @@ -76,10 +76,17 @@ enum WorkspacePlanStatuses { expired } +enum WorkspacePaymentMethod { + unpaid + invoice + billing +} + type WorkspacePlan { name: WorkspacePlans! status: WorkspacePlanStatuses! createdAt: DateTime! + paymentMethod: WorkspacePaymentMethod! } type WorkspaceSubscriptionSeats { diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index e38052d2ad..6d2b1fdaff 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -4534,10 +4534,17 @@ export type WorkspaceMutationsUpdateRoleArgs = { input: WorkspaceRoleUpdateInput; }; +export enum WorkspacePaymentMethod { + Billing = 'billing', + Invoice = 'invoice', + Unpaid = 'unpaid' +} + export type WorkspacePlan = { __typename?: 'WorkspacePlan'; createdAt: Scalars['DateTime']['output']; name: WorkspacePlans; + paymentMethod: WorkspacePaymentMethod; status: WorkspacePlanStatuses; }; @@ -5062,6 +5069,7 @@ export type ResolversTypes = { WorkspaceJoinRequestMutations: ResolverTypeWrapper; WorkspaceJoinRequestStatus: WorkspaceJoinRequestStatus; WorkspaceMutations: ResolverTypeWrapper; + WorkspacePaymentMethod: WorkspacePaymentMethod; WorkspacePlan: ResolverTypeWrapper; WorkspacePlanStatuses: WorkspacePlanStatuses; WorkspacePlans: WorkspacePlans; @@ -6906,6 +6914,7 @@ export type WorkspaceMutationsResolvers = { createdAt?: Resolver; name?: Resolver; + paymentMethod?: Resolver; status?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index b69b023c03..cc50cbc69e 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -4515,10 +4515,17 @@ export type WorkspaceMutationsUpdateRoleArgs = { input: WorkspaceRoleUpdateInput; }; +export enum WorkspacePaymentMethod { + Billing = 'billing', + Invoice = 'invoice', + Unpaid = 'unpaid' +} + export type WorkspacePlan = { __typename?: 'WorkspacePlan'; createdAt: Scalars['DateTime']['output']; name: WorkspacePlans; + paymentMethod: WorkspacePaymentMethod; status: WorkspacePlanStatuses; }; diff --git a/packages/server/modules/gatekeeper/graph/resolvers/index.ts b/packages/server/modules/gatekeeper/graph/resolvers/index.ts index 6a5a6c1849..55e3de94a3 100644 --- a/packages/server/modules/gatekeeper/graph/resolvers/index.ts +++ b/packages/server/modules/gatekeeper/graph/resolvers/index.ts @@ -2,7 +2,7 @@ import { getFeatureFlags, getFrontendOrigin } from '@/modules/shared/helpers/env import { Resolvers } from '@/modules/core/graph/generated/graphql' import { pricingTable } from '@/modules/gatekeeper/domain/workspacePricing' import { authorizeResolver } from '@/modules/shared' -import { Roles } from '@speckle/shared' +import { Roles, throwUncoveredError } from '@speckle/shared' import { countWorkspaceRoleWithOptionalProjectRoleFactory, getWorkspaceFactory @@ -33,6 +33,7 @@ import { canWorkspaceAccessFeatureFactory } from '@/modules/gatekeeper/services/ import { upgradeWorkspaceSubscriptionFactory } from '@/modules/gatekeeper/services/subscriptions' import { isWorkspaceReadOnlyFactory } from '@/modules/gatekeeper/services/readOnly' import { calculateSubscriptionSeats } from '@/modules/gatekeeper/domain/billing' +import { WorkspacePaymentMethod } from '@/test/graphql/generated/graphql' const { FF_GATEKEEPER_MODULE_ENABLED } = getFeatureFlags() @@ -47,7 +48,30 @@ export = FF_GATEKEEPER_MODULE_ENABLED }, Workspace: { plan: async (parent) => { - return await getWorkspacePlanFactory({ db })({ workspaceId: parent.id }) + const workspacePlan = await getWorkspacePlanFactory({ db })({ + workspaceId: parent.id + }) + if (!workspacePlan) return null + let paymentMethod: WorkspacePaymentMethod + switch (workspacePlan.name) { + case 'starter': + case 'plus': + case 'business': + paymentMethod = WorkspacePaymentMethod.Billing + break + case 'unlimited': + case 'academia': + paymentMethod = WorkspacePaymentMethod.Unpaid + break + case 'starterInvoiced': + case 'plusInvoiced': + case 'businessInvoiced': + paymentMethod = WorkspacePaymentMethod.Invoice + break + default: + throwUncoveredError(workspacePlan) + } + return { ...workspacePlan, paymentMethod } }, subscription: async (parent) => { const workspaceId = parent.id diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 7a0b418b7e..046fce71c7 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -4516,10 +4516,17 @@ export type WorkspaceMutationsUpdateRoleArgs = { input: WorkspaceRoleUpdateInput; }; +export enum WorkspacePaymentMethod { + Billing = 'billing', + Invoice = 'invoice', + Unpaid = 'unpaid' +} + export type WorkspacePlan = { __typename?: 'WorkspacePlan'; createdAt: Scalars['DateTime']['output']; name: WorkspacePlans; + paymentMethod: WorkspacePaymentMethod; status: WorkspacePlanStatuses; };