diff --git a/apiserver/plane/payment/urls.py b/apiserver/plane/payment/urls.py index 5d0e7c64a2..0da4237c9d 100644 --- a/apiserver/plane/payment/urls.py +++ b/apiserver/plane/payment/urls.py @@ -12,6 +12,7 @@ from .views import ( WorkspaceLicenseRefreshEndpoint, WorkspaceLicenseSyncEndpoint, WorkspaceFreeTrialEndpoint, + WorkspaceTrialUpgradeEndpoint, ) urlpatterns = [ @@ -68,6 +69,11 @@ urlpatterns = [ path( "workspaces//trial-subscriptions/", WorkspaceFreeTrialEndpoint.as_view(), - name="license-refresh", + name="trial-subscriptions", + ), + path( + "workspaces//trial-subscriptions/upgrade/", + WorkspaceTrialUpgradeEndpoint.as_view(), + name="trial-upgrade", ), ] diff --git a/apiserver/plane/payment/views/__init__.py b/apiserver/plane/payment/views/__init__.py index 952c900af0..d8c424491d 100644 --- a/apiserver/plane/payment/views/__init__.py +++ b/apiserver/plane/payment/views/__init__.py @@ -9,6 +9,7 @@ from .payment import ( PaymentLinkEndpoint, WebsitePaymentLinkEndpoint, WorkspaceFreeTrialEndpoint, + WorkspaceTrialUpgradeEndpoint, ) from .subscription import SubscriptionEndpoint, UpgradeSubscriptionEndpoint from .feature_flag import FeatureFlagProxyEndpoint diff --git a/apiserver/plane/payment/views/payment.py b/apiserver/plane/payment/views/payment.py index 31f9626664..665600ac21 100644 --- a/apiserver/plane/payment/views/payment.py +++ b/apiserver/plane/payment/views/payment.py @@ -260,3 +260,60 @@ class WorkspaceFreeTrialEndpoint(BaseAPIView): {"error": "error fetching payment link"}, status=status.HTTP_400_BAD_REQUEST, ) + + +class WorkspaceTrialUpgradeEndpoint(BaseAPIView): + + permission_classes = [ + WorkspaceOwnerPermission, + ] + + def post(self, request, slug): + try: + # Get the product_id and price_id + price_id = request.data.get("price_id", False) + + # Check if product_id and price_id are present + if not price_id: + return Response( + {"error": "price_id is required"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + # Get the workspace + workspace = Workspace.objects.get(slug=slug) + + # Check if the payment server base url is present + if settings.PAYMENT_SERVER_BASE_URL: + response = requests.post( + f"{settings.PAYMENT_SERVER_BASE_URL}/api/trial-subscriptions/upgrade/", + headers={ + "content-type": "application/json", + "x-api-key": settings.PAYMENT_SERVER_AUTH_TOKEN, + }, + json={ + "workspace_id": str(workspace.id), + "stripe_price_id": price_id, + }, + ) + # Check if the response is successful + response.raise_for_status() + # Convert the response to json + response = response.json() + return Response(response, status=status.HTTP_200_OK) + else: + return Response( + {"error": "error fetching product details"}, + status=status.HTTP_400_BAD_REQUEST, + ) + except requests.exceptions.RequestException as e: + if e.response.status_code == 400: + return Response( + e.response.json(), + status=status.HTTP_400_BAD_REQUEST, + ) + log_exception(e) + return Response( + {"error": "error fetching payment link"}, + status=status.HTTP_400_BAD_REQUEST, + ) diff --git a/web/ee/components/license/pro-plan-cloud-upgrade-modal.tsx b/web/ee/components/license/pro-plan-cloud-upgrade-modal.tsx index b7b8f0303d..0869502848 100644 --- a/web/ee/components/license/pro-plan-cloud-upgrade-modal.tsx +++ b/web/ee/components/license/pro-plan-cloud-upgrade-modal.tsx @@ -152,7 +152,7 @@ export const ProPlanCloudUpgradeModal: FC = (prop }; // handling the payment link when the free trial is enabled - const handleSubscriptionPageRedirection = () => { + const handleSubscriptionPageRedirection = (priceId: string) => { if (!workspaceSlug) return; if (!isAdmin) { @@ -166,10 +166,10 @@ export const ProPlanCloudUpgradeModal: FC = (prop setLoading(true); paymentService - .getWorkspaceSubscriptionPageLink(workspaceSlug.toString()) + .modifyTrailSubscription(workspaceSlug.toString(), { price_id: priceId }) .then((response) => { - if (response.url) { - window.open(response.url, "_blank"); + if (response.session_url) { + window.open(response.session_url, "_blank"); } }) .catch(() => { @@ -267,7 +267,7 @@ export const ProPlanCloudUpgradeModal: FC = (prop features={PRO_PLAN_FEATURES_MAP} isLoading={isLoading} handlePaymentLink={(priceId: string) => - isInTrailPeriod ? handleSubscriptionPageRedirection() : handlePaymentLink(priceId) + isInTrailPeriod ? handleSubscriptionPageRedirection(priceId) : handlePaymentLink(priceId) } yearlyPlanOnly={yearlyPlan} trialLoader={trialLoader} diff --git a/web/ee/services/payment.service.ts b/web/ee/services/payment.service.ts index 0c0ee7c001..7caf933fe9 100644 --- a/web/ee/services/payment.service.ts +++ b/web/ee/services/payment.service.ts @@ -72,4 +72,15 @@ export class PaymentService extends APIService { throw error?.response?.data; }); } + + async modifyTrailSubscription( + workspaceSlug: string, + payload: { price_id: string } + ): Promise<{ session_url: string }> { + return this.post(`/api/payments/workspaces/${workspaceSlug}/trial-subscriptions/upgrade/`, payload) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } } diff --git a/web/ee/store/subscription/subscription.store.ts b/web/ee/store/subscription/subscription.store.ts index 9bfbb10c88..a6a8a16c59 100644 --- a/web/ee/store/subscription/subscription.store.ts +++ b/web/ee/store/subscription/subscription.store.ts @@ -36,6 +36,7 @@ export class WorkspaceSubscriptionStore implements IWorkspaceSubscriptionStore { toggleProPlanModal: action, fetchWorkspaceSubscribedPlan: action, refreshWorkspaceSubscribedPlan: action, + freeTrialSubscription: action, }); }