diff --git a/packages/backend/src/graphql/queries/get-billing-and-usage.ee.js b/packages/backend/src/graphql/queries/get-billing-and-usage.ee.js deleted file mode 100644 index d23a44e5..00000000 --- a/packages/backend/src/graphql/queries/get-billing-and-usage.ee.js +++ /dev/null @@ -1,101 +0,0 @@ -import { DateTime } from 'luxon'; -import Billing from '../../helpers/billing/index.ee.js'; -import ExecutionStep from '../../models/execution-step.js'; - -const getBillingAndUsage = async (_parent, _params, context) => { - const persistedSubscription = await context.currentUser.$relatedQuery( - 'currentSubscription' - ); - - const subscription = persistedSubscription - ? paidSubscription(persistedSubscription) - : freeTrialSubscription(); - - return { - subscription, - usage: { - task: executionStepCount(context), - }, - }; -}; - -const paidSubscription = (subscription) => { - const currentPlan = Billing.paddlePlans.find( - (plan) => plan.productId === subscription.paddlePlanId - ); - - return { - status: subscription.status, - monthlyQuota: { - title: currentPlan.limit, - action: { - type: 'link', - text: 'Cancel plan', - src: subscription.cancelUrl, - }, - }, - nextBillAmount: { - title: subscription.nextBillAmount - ? '€' + subscription.nextBillAmount - : '---', - action: { - type: 'link', - text: 'Update payment method', - src: subscription.updateUrl, - }, - }, - nextBillDate: { - title: subscription.nextBillDate ? subscription.nextBillDate : '---', - action: { - type: 'text', - text: '(monthly payment)', - }, - }, - }; -}; - -const freeTrialSubscription = () => { - return { - status: null, - monthlyQuota: { - title: 'Free Trial', - action: { - type: 'link', - text: 'Upgrade plan', - src: '/settings/billing/upgrade', - }, - }, - nextBillAmount: { - title: '---', - action: null, - }, - nextBillDate: { - title: '---', - action: null, - }, - }; -}; - -const executionIds = async (context) => { - return ( - await context.currentUser - .$relatedQuery('executions') - .select('executions.id') - ).map((execution) => execution.id); -}; - -const executionStepCount = async (context) => { - const executionStepCount = await ExecutionStep.query() - .whereIn('execution_id', await executionIds(context)) - .andWhere( - 'created_at', - '>=', - DateTime.now().minus({ days: 30 }).toISODate() - ) - .count() - .first(); - - return executionStepCount.count; -}; - -export default getBillingAndUsage; diff --git a/packages/backend/src/graphql/query-resolvers.js b/packages/backend/src/graphql/query-resolvers.js index 1fb2619c..ca40ba8f 100644 --- a/packages/backend/src/graphql/query-resolvers.js +++ b/packages/backend/src/graphql/query-resolvers.js @@ -1,6 +1,5 @@ import getApp from './queries/get-app.js'; import getAppAuthClient from './queries/get-app-auth-client.ee.js'; -import getBillingAndUsage from './queries/get-billing-and-usage.ee.js'; import getConnectedApps from './queries/get-connected-apps.js'; import getDynamicData from './queries/get-dynamic-data.js'; import getStepWithTestExecutions from './queries/get-step-with-test-executions.js'; @@ -9,7 +8,6 @@ import testConnection from './queries/test-connection.js'; const queryResolvers = { getApp, getAppAuthClient, - getBillingAndUsage, getConnectedApps, getDynamicData, getStepWithTestExecutions, diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index fe1b44b5..f9c9cc2d 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -9,7 +9,6 @@ type Query { key: String! parameters: JSONObject ): JSONObject - getBillingAndUsage: GetBillingAndUsage } type Mutation { @@ -561,43 +560,6 @@ type License { verified: Boolean } -type GetBillingAndUsage { - subscription: Subscription - usage: Usage -} - -type MonthlyQuota { - title: String - action: BillingCardAction -} - -type NextBillAmount { - title: String - action: BillingCardAction -} - -type NextBillDate { - title: String - action: BillingCardAction -} - -type BillingCardAction { - type: String - text: String - src: String -} - -type Subscription { - status: String - monthlyQuota: MonthlyQuota - nextBillAmount: NextBillAmount - nextBillDate: NextBillDate -} - -type Usage { - task: Int -} - type Permission { id: String action: String diff --git a/packages/web/src/components/CheckoutCompletedAlert/index.ee.jsx b/packages/web/src/components/CheckoutCompletedAlert/index.ee.jsx index a1b75643..d236987a 100644 --- a/packages/web/src/components/CheckoutCompletedAlert/index.ee.jsx +++ b/packages/web/src/components/CheckoutCompletedAlert/index.ee.jsx @@ -1,14 +1,17 @@ import * as React from 'react'; +import { useLocation } from 'react-router-dom'; import Alert from '@mui/material/Alert'; import Typography from '@mui/material/Typography'; + import useFormatMessage from 'hooks/useFormatMessage'; -import useSubscription from 'hooks/useSubscription.ee'; export default function CheckoutCompletedAlert() { const formatMessage = useFormatMessage(); - const subscription = useSubscription(); + const location = useLocation(); + const state = location.state; + const checkoutCompleted = state?.checkoutCompleted; - if (subscription?.data?.status !== 'active') return ; + if (!checkoutCompleted) return ; return ( { const { data } = usePaddleInfo(); const sandbox = data?.data?.sandbox; const vendorId = data?.data?.vendorId; + const queryClient = useQueryClient(); const [loaded, setLoaded] = React.useState(false); @@ -29,8 +30,12 @@ export const PaddleProvider = (props) => { if (completed) { // Paddle has side effects in the background, // so we need to refetch the relevant queries - await apolloClient.refetchQueries({ - include: ['GetTrialStatus', 'GetBillingAndUsage'], + await queryClient.refetchQueries({ + queryKey: ['userTrial'], + }); + + await queryClient.refetchQueries({ + queryKey: ['subscription'], }); navigate(URLS.SETTINGS_BILLING_AND_USAGE, { @@ -39,7 +44,7 @@ export const PaddleProvider = (props) => { } } }, - [navigate], + [navigate, queryClient], ); const value = React.useMemo(() => { diff --git a/packages/web/src/graphql/queries/get-billing-and-usage.ee.js b/packages/web/src/graphql/queries/get-billing-and-usage.ee.js deleted file mode 100644 index 726b2b8e..00000000 --- a/packages/web/src/graphql/queries/get-billing-and-usage.ee.js +++ /dev/null @@ -1,37 +0,0 @@ -import { gql } from '@apollo/client'; -export const GET_BILLING_AND_USAGE = gql` - query GetBillingAndUsage { - getBillingAndUsage { - subscription { - status - monthlyQuota { - title - action { - type - text - src - } - } - nextBillDate { - title - action { - type - text - src - } - } - nextBillAmount { - title - action { - type - text - src - } - } - } - usage { - task - } - } - } -`; diff --git a/packages/web/src/hooks/useBillingAndUsageData.ee.js b/packages/web/src/hooks/useBillingAndUsageData.ee.js deleted file mode 100644 index 999402ff..00000000 --- a/packages/web/src/hooks/useBillingAndUsageData.ee.js +++ /dev/null @@ -1,52 +0,0 @@ -import * as React from 'react'; -import { useQuery } from '@apollo/client'; -import { useLocation } from 'react-router-dom'; -import { DateTime } from 'luxon'; -import { GET_BILLING_AND_USAGE } from 'graphql/queries/get-billing-and-usage.ee'; -function transform(billingAndUsageData) { - const nextBillDate = billingAndUsageData.subscription.nextBillDate; - const nextBillDateTitle = nextBillDate.title; - const nextBillDateTitleDateObject = DateTime.fromMillis( - Number(nextBillDateTitle), - ); - const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid - ? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy') - : nextBillDateTitle; - return { - ...billingAndUsageData, - subscription: { - ...billingAndUsageData.subscription, - nextBillDate: { - ...billingAndUsageData.subscription.nextBillDate, - title: formattedNextBillDateTitle, - }, - }, - }; -} -export default function useBillingAndUsageData() { - const location = useLocation(); - const state = location.state; - const { data, loading, startPolling, stopPolling } = useQuery( - GET_BILLING_AND_USAGE, - ); - const checkoutCompleted = state?.checkoutCompleted; - const hasSubscription = !!data?.getBillingAndUsage?.subscription?.status; - React.useEffect( - function pollDataUntilSubscriptionIsCreated() { - if (checkoutCompleted && !hasSubscription) { - startPolling(1000); - } - }, - [checkoutCompleted, hasSubscription, startPolling], - ); - React.useEffect( - function stopPollingWhenSubscriptionIsCreated() { - if (checkoutCompleted && hasSubscription) { - stopPolling(); - } - }, - [checkoutCompleted, hasSubscription, stopPolling], - ); - if (loading) return null; - return transform(data.getBillingAndUsage); -} diff --git a/packages/web/src/hooks/useSubscription.ee.js b/packages/web/src/hooks/useSubscription.ee.js index 2be6e9a9..9f8ae544 100644 --- a/packages/web/src/hooks/useSubscription.ee.js +++ b/packages/web/src/hooks/useSubscription.ee.js @@ -24,7 +24,7 @@ export default function useSubscription() { const checkoutCompleted = state?.checkoutCompleted; const [isPolling, setIsPolling] = React.useState(false); - const { data, isLoading: isSubscriptionLoading } = useQuery({ + const { data } = useQuery({ queryKey: ['subscription'], queryFn: async ({ signal }) => { const { data } = await api.get(`/v1/users/me/subscription`, { @@ -38,32 +38,17 @@ export default function useSubscription() { const subscription = data?.data; - const hasSubscription = !!subscription?.status; + const hasSubscription = subscription?.status === 'active'; React.useEffect( function pollDataUntilSubscriptionIsCreated() { - if (checkoutCompleted && !hasSubscription) { - setIsPolling(true); + if (checkoutCompleted) { + setIsPolling(!hasSubscription); } }, [checkoutCompleted, hasSubscription], ); - React.useEffect( - function stopPollingWhenSubscriptionIsCreated() { - if (checkoutCompleted && hasSubscription) { - setIsPolling(false); - } - }, - [checkoutCompleted, hasSubscription], - ); - - const cancellationEffectiveDate = subscription?.cancellationEffectiveDate; - - const hasCancelled = !!cancellationEffectiveDate; - - if (isSubscriptionLoading || !hasCancelled) return null; - return { data: transform(subscription), };