Refresh billing state after ending trial period (#23534)
Fixes #23530 After adding a credit card in the billing prompt, the credits section and subscription details stayed stale until a full page refresh. The `endSubscriptionTrialPeriod` mutation only returned `status` and `hasPaymentMethod`, and the frontend hook only patched the subscription status into the workspace state. The credits query was never refetched, so granted credits kept showing trial values, and `currentPeriodEnd` (renewal date) and `billingCustomer.hasPaymentMethod` stayed outdated. The backend already syncs everything to the database synchronously before the mutation returns, so fresh data was available, just never fetched. Changes: - `BillingEndTrialPeriodDTO` now includes nullable `currentBillingSubscription` and `billingSubscriptions`, returned by the resolver on success, mirroring the other billing update mutations (`switchSubscriptionInterval`, etc.) - `useEndSubscriptionTrialPeriod` applies the full billing update via `useApplyCurrentWorkspaceBillingUpdate` (falling back to the previous status-only patch), marks the billing customer as having a payment method, and refetches `GetResourceCreditUsage` so the credits section updates for any active observer This covers all entry points that end the trial: the billing page card modal, the trial banner, the AI chat banner, and the return from the Stripe portal. --- _Generated by [Claude Code](https://claude.ai/code/session_01W1J7cW2MhaqXGfdjvHeFoX)_ <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23534?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+6
@@ -6,6 +6,12 @@ export const END_SUBSCRIPTION_TRIAL_PERIOD = gql`
|
||||
status
|
||||
hasPaymentMethod
|
||||
billingPortalUrl
|
||||
currentBillingSubscription {
|
||||
...CurrentBillingSubscriptionFragment
|
||||
}
|
||||
billingSubscriptions {
|
||||
...BillingSubscriptionFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
+35
@@ -1,6 +1,7 @@
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
|
||||
import { START_SUBSCRIPTION_AFTER_PAYMENT_METHOD_QUERY_PARAM } from '@/settings/billing/constants/StartSubscriptionAfterPaymentMethodQueryParam';
|
||||
import { useApplyCurrentWorkspaceBillingUpdate } from '@/settings/billing/hooks/useApplyCurrentWorkspaceBillingUpdate';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -11,6 +12,7 @@ import { useLazyQuery, useMutation } from '@apollo/client/react';
|
||||
import {
|
||||
BillingPortalSessionDocument,
|
||||
EndSubscriptionTrialPeriodDocument,
|
||||
GetResourceCreditUsageDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useEndSubscriptionTrialPeriod = () => {
|
||||
@@ -18,11 +20,16 @@ export const useEndSubscriptionTrialPeriod = () => {
|
||||
useSnackBar();
|
||||
const [endSubscriptionTrialPeriod] = useMutation(
|
||||
EndSubscriptionTrialPeriodDocument,
|
||||
{
|
||||
refetchQueries: [GetResourceCreditUsageDocument],
|
||||
},
|
||||
);
|
||||
const [getBillingPortalSession] = useLazyQuery(BillingPortalSessionDocument);
|
||||
const [currentWorkspace, setCurrentWorkspace] = useAtomState(
|
||||
currentWorkspaceState,
|
||||
);
|
||||
const { applyCurrentWorkspaceBillingUpdate } =
|
||||
useApplyCurrentWorkspaceBillingUpdate();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { redirect } = useRedirect();
|
||||
const location = useLocation();
|
||||
@@ -96,8 +103,23 @@ export const useEndSubscriptionTrialPeriod = () => {
|
||||
return { success: false, hasPaymentMethod: false };
|
||||
}
|
||||
|
||||
const updatedCurrentBillingSubscription =
|
||||
endTrialPeriodOutput?.currentBillingSubscription;
|
||||
const updatedBillingSubscriptions =
|
||||
endTrialPeriodOutput?.billingSubscriptions;
|
||||
|
||||
const hasAppliedFullBillingUpdate =
|
||||
isDefined(updatedCurrentBillingSubscription) &&
|
||||
isDefined(updatedBillingSubscriptions)
|
||||
? applyCurrentWorkspaceBillingUpdate({
|
||||
currentBillingSubscription: updatedCurrentBillingSubscription,
|
||||
billingSubscriptions: updatedBillingSubscriptions,
|
||||
})
|
||||
: false;
|
||||
|
||||
const updatedSubscriptionStatus = endTrialPeriodOutput?.status;
|
||||
if (
|
||||
!hasAppliedFullBillingUpdate &&
|
||||
isDefined(updatedSubscriptionStatus) &&
|
||||
isDefined(currentWorkspace?.currentBillingSubscription)
|
||||
) {
|
||||
@@ -117,6 +139,19 @@ export const useEndSubscriptionTrialPeriod = () => {
|
||||
});
|
||||
}
|
||||
|
||||
setCurrentWorkspace((previousWorkspace) =>
|
||||
isDefined(previousWorkspace) &&
|
||||
isDefined(previousWorkspace.billingCustomer)
|
||||
? {
|
||||
...previousWorkspace,
|
||||
billingCustomer: {
|
||||
...previousWorkspace.billingCustomer,
|
||||
hasPaymentMethod: true,
|
||||
},
|
||||
}
|
||||
: previousWorkspace,
|
||||
);
|
||||
|
||||
enqueueSuccessSnackBar({
|
||||
message: t`Subscription activated.`,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user