route('app.welcome.persona'); } public function processing(Request $request): Response|RedirectResponse { if (config('trypost.self_hosted')) { return redirect()->route('app.calendar'); } $user = $request->user(); $account = $user->accountOrFail(); $subscriptionActive = $account->subscribed(Account::SUBSCRIPTION_NAME); $redirectToOnboarding = $user->isAccountOwner() && $account->isOnboardingOpen(); return Inertia::render('billing/Processing', [ 'subscriptionActive' => $subscriptionActive, 'redirectToOnboarding' => $redirectToOnboarding, ]); } public function index(Request $request): Response|RedirectResponse { if (config('trypost.self_hosted')) { return redirect()->route('app.calendar'); } $account = $request->user()->account; abort_unless($request->user()->isAccountOwner(), SymfonyResponse::HTTP_FORBIDDEN); $subscription = $account->subscription(Account::SUBSCRIPTION_NAME); return Inertia::render('settings/account/Billing', [ 'hasSubscription' => $account->subscribed(Account::SUBSCRIPTION_NAME), 'onTrial' => $account->isOnTrial(), 'trialEndsAt' => $account->activeTrialEndsAt(), 'subscription' => $subscription?->only([ 'stripe_status', 'ends_at', ]), 'plan' => $account->plan, 'workspaceCount' => $account->workspaces()->count(), 'invoices' => $account->invoices()->map(fn ($invoice) => [ 'id' => $invoice->id, 'date' => $invoice->date(), 'total' => $invoice->total(), 'status' => $invoice->status, 'invoice_pdf' => $invoice->invoice_pdf, ]), 'defaultPaymentMethod' => $account->displayablePaymentMethod(), ]); } public function swapToYearly(Request $request): RedirectResponse { if (config('trypost.self_hosted')) { return redirect()->route('app.calendar'); } $account = $request->user()->account; abort_unless($request->user()->isAccountOwner(), SymfonyResponse::HTTP_FORBIDDEN); abort_unless($account->subscribed(Account::SUBSCRIPTION_NAME), SymfonyResponse::HTTP_UNPROCESSABLE_ENTITY, 'No active subscription'); $plan = $account->plan; $yearlyPriceId = $plan?->stripe_yearly_price_id; abort_if($yearlyPriceId === null, SymfonyResponse::HTTP_UNPROCESSABLE_ENTITY, 'No annual price configured'); $subscription = $account->subscription(Account::SUBSCRIPTION_NAME); abort_if($subscription === null, SymfonyResponse::HTTP_UNPROCESSABLE_ENTITY, 'No active subscription'); if ($subscription->stripe_price === $yearlyPriceId) { return redirect()->route('app.billing.index'); } $authorization = Gate::inspect('swapPlan', [$account]); if ($authorization->denied()) { return back()->with('flash.error', $authorization->message()); } $subscription->swap($yearlyPriceId); return redirect()->route('app.billing.index') ->with('flash.success', __('billing.flash.switched_to_yearly')); } public function portal(Request $request): RedirectResponse { if (config('trypost.self_hosted')) { return redirect()->route('app.calendar'); } $account = $request->user()->account; abort_unless($request->user()->isAccountOwner(), SymfonyResponse::HTTP_FORBIDDEN); return $account->redirectToBillingPortal( route('app.billing.index') ); } }