user(); // Company users see only active plans if ($user->type !== 'superadmin') { return $this->companyPlansView($request); } // Admin view $billingCycle = $request->input('billing_cycle', 'monthly'); $dbPlans = Plan::all(); $hasDefaultPlan = $dbPlans->where('is_default', true)->count() > 0; $settings = settings(); // Always use super admin currency for plan pricing $superAdmin = User::where('type', 'superadmin')->first(); $superAdminSettings = settings($superAdmin->id); $currency = $superAdminSettings ? ($superAdminSettings['defaultCurrency'] ?? 'USD') : 'USD'; $currencySymbol = '$'; if (!empty($currency)) { $currencyData = Currency::where('code', $currency)->first(); $currencySymbol = $currencyData ? $currencyData->symbol : '$'; } $plans = $dbPlans->map(function ($plan) use ($billingCycle) { // Determine features based on plan attributes $features = []; if ($plan->enable_chatgpt === 'on') $features[] = 'AI Integration'; // Get price based on billing cycle $price = $billingCycle === 'yearly' ? $plan->yearly_price : $plan->price; // Format price with currency symbol $formattedPrice = '$' . number_format($price, 2); // Set duration based on billing cycle $duration = $billingCycle === 'yearly' ? 'Yearly' : 'Monthly'; return [ 'id' => $plan->id, 'name' => $plan->name, 'price' => $price, 'formattedPrice' => $formattedPrice, 'duration' => $duration, 'description' => $plan->description, 'trial_days' => $plan->trial_day, 'features' => $features, 'stats' => [ 'users' => $plan->max_users, 'employees' => $plan->max_employees, 'storage' => $plan->storage_limit . ' GB' ], 'status' => $plan->is_plan_enable === 'on', 'is_default' => $plan->is_default, 'recommended' => false // Default to false ]; })->toArray(); // Mark the plan with most subscribers as recommended $planSubscriberCounts = Plan::withCount('users')->get()->pluck('users_count', 'id'); $mostSubscribedPlanId = $planSubscriberCounts->keys()->first(); if ($planSubscriberCounts->isNotEmpty()) { $mostSubscribedPlanId = $planSubscriberCounts->keys()->sortByDesc(function ($planId) use ($planSubscriberCounts) { return $planSubscriberCounts[$planId]; })->first(); } foreach ($plans as &$plan) { if ($plan['id'] == $mostSubscribedPlanId && $plan['price'] != '0') { $plan['recommended'] = true; break; } } return Inertia::render('plans/index', [ 'plans' => $plans, 'billingCycle' => $billingCycle, 'hasDefaultPlan' => $hasDefaultPlan, 'isAdmin' => true, 'currency' => $currency, 'currencySymbol' => $currencySymbol ]); } /** * Toggle plan status */ public function toggleStatus(Plan $plan) { $plan->is_plan_enable = $plan->is_plan_enable === 'on' ? 'off' : 'on'; $plan->save(); $status = $plan->is_plan_enable === 'on' ? 'activated' : 'deactivated'; return back()->with('success', __('Plan :status successfully', ['status' => $status])); } /** * Show the form for creating a new plan */ public function create() { $hasDefaultPlan = Plan::where('is_default', true)->exists(); return Inertia::render('plans/create', [ 'hasDefaultPlan' => $hasDefaultPlan ]); } /** * Store a newly created plan */ public function store(Request $request) { $validated = $request->validate([ 'name' => 'required|string|max:100|unique:plans', 'price' => 'required|numeric|min:0', 'yearly_price' => 'nullable|numeric|min:0', 'duration' => 'required|string', 'description' => 'nullable|string', 'max_users' => 'required|integer|min:0', 'max_employees' => 'required|integer|min:0', 'storage_limit' => 'required|numeric|min:0', 'enable_chatgpt' => 'nullable|in:on,off', 'is_trial' => 'nullable|in:on,off', 'trial_day' => 'nullable|integer|min:0', 'is_plan_enable' => 'nullable|in:on,off', 'is_default' => 'nullable|boolean', ]); // Set default values for nullable fields $validated['enable_chatgpt'] = $validated['enable_chatgpt'] ?? 'off'; $validated['is_trial'] = $validated['is_trial'] ?? null; $validated['is_plan_enable'] = $validated['is_plan_enable'] ?? 'on'; $validated['is_default'] = $validated['is_default'] ?? false; // If yearly_price is not provided, calculate it as 80% of monthly price * 12 if (!isset($validated['yearly_price']) || $validated['yearly_price'] === null) { $validated['yearly_price'] = $validated['price'] * 12 * 0.8; } // If this plan is set as default, remove default status from other plans if ($validated['is_default']) { Plan::where('is_default', true)->update(['is_default' => false]); } // Create the plan Plan::create($validated); return redirect()->route('plans.index')->with('success', __('Plan created successfully.')); } /** * Show the form for editing a plan */ public function edit(Plan $plan) { $otherDefaultPlanExists = Plan::where('is_default', true) ->where('id', '!=', $plan->id) ->exists(); return Inertia::render('plans/edit', [ 'plan' => $plan, 'otherDefaultPlanExists' => $otherDefaultPlanExists ]); } /** * Update a plan */ public function update(Request $request, Plan $plan) { $validated = $request->validate([ 'name' => 'required|string|max:100|unique:plans,name,' . $plan->id, 'price' => 'required|numeric|min:0', 'yearly_price' => 'nullable|numeric|min:0', 'duration' => 'required|string', 'description' => 'nullable|string', 'max_users' => 'required|integer|min:0', 'max_employees' => 'required|integer|min:0', 'storage_limit' => 'required|numeric|min:0', 'enable_chatgpt' => 'nullable|in:on,off', 'is_trial' => 'nullable|in:on,off', 'trial_day' => 'nullable|integer|min:0', 'is_plan_enable' => 'nullable|in:on,off', 'is_default' => 'nullable|boolean', ]); // Set default values for nullable fields $validated['enable_chatgpt'] = $validated['enable_chatgpt'] ?? 'off'; $validated['is_trial'] = $validated['is_trial'] ?? null; $validated['is_plan_enable'] = $validated['is_plan_enable'] ?? 'on'; $validated['is_default'] = $validated['is_default'] ?? false; // If yearly_price is not provided, calculate it as 80% of monthly price * 12 if (!isset($validated['yearly_price']) || $validated['yearly_price'] === null) { $validated['yearly_price'] = $validated['price'] * 12 * 0.8; } // If this plan is set as default, remove default status from other plans if ($validated['is_default'] && !$plan->is_default) { Plan::where('is_default', true)->update(['is_default' => false]); } // Update the plan $plan->update($validated); return redirect()->route('plans.index')->with('success', __('Plan updated successfully.')); } /** * Delete a plan */ public function destroy(Plan $plan) { // Don't allow deleting the default plan if ($plan->is_default) { return back()->with('error', __('Cannot delete the default plan.')); } $plan->delete(); return redirect()->route('plans.index')->with('success', __('Plan deleted successfully.')); } private function companyPlansView(Request $request) { $user = auth()->user(); $billingCycle = $request->input('billing_cycle', 'monthly'); $dbPlans = Plan::where('is_plan_enable', 'on')->get(); // Always use super admin currency for plan pricing $superAdmin = User::where('type', 'superadmin')->first(); $superAdminSettings = settings($superAdmin->id); $currency = $superAdminSettings ? ($superAdminSettings['defaultCurrency'] ?? 'USD') : 'USD'; $currencySymbol = '$'; if (!empty($currency)) { $currencyData = Currency::where('code', $currency)->first(); $currencySymbol = $currencyData ? $currencyData->symbol : '$'; } $plans = $dbPlans->map(function ($plan) use ($billingCycle, $user) { $price = $billingCycle === 'yearly' ? $plan->yearly_price : $plan->price; $features = []; if ($plan->enable_chatgpt === 'on') $features[] = 'AI Integration'; return [ 'id' => $plan->id, 'name' => $plan->name, 'price' => $price, 'formatted_price' => number_format($price, 2), 'duration' => $billingCycle === 'yearly' ? 'Yearly' : 'Monthly', 'description' => $plan->description, 'trial_days' => $plan->trial_day, 'features' => $features, 'stats' => [ 'users' => $plan->max_users, 'employees' => $plan->max_employees, 'storage' => $plan->storage_limit . ' GB' ], 'is_current' => $user->plan_id == $plan->id, 'is_trial_available' => $plan->is_trial === 'on' && !$user->is_trial, 'is_default' => $plan->is_default, 'recommended' => false // Default to false ]; }); // Mark the plan with most subscribers as recommended $planSubscriberCounts = Plan::withCount('users')->get()->pluck('users_count', 'id'); if ($planSubscriberCounts->isNotEmpty()) { $mostSubscribedPlanId = $planSubscriberCounts->keys()->sortByDesc(function ($planId) use ($planSubscriberCounts) { return $planSubscriberCounts[$planId]; })->first(); $plans = $plans->map(function ($plan) use ($mostSubscribedPlanId) { if ($plan['id'] == $mostSubscribedPlanId) { $plan['recommended'] = true; } return $plan; }); } return Inertia::render('plans/index', [ 'plans' => $plans, 'billingCycle' => $billingCycle, 'currentPlan' => $user->plan, 'userTrialUsed' => $user->is_trial, 'currency' => $currency, 'currencySymbol' => $currencySymbol ]); } public function requestPlan(Request $request) { $request->validate([ 'plan_id' => 'required|exists:plans,id', 'billing_cycle' => 'required|in:monthly,yearly' ]); $user = auth()->user(); $plan = Plan::findOrFail($request->plan_id); \App\Models\PlanRequest::create([ 'user_id' => $user->id, 'plan_id' => $plan->id, 'duration' => $request->billing_cycle, 'status' => 'pending' ]); return back()->with('success', __('Plan request submitted successfully')); } public function startTrial(Request $request) { $request->validate([ 'plan_id' => 'required|exists:plans,id' ]); $user = auth()->user(); $plan = Plan::findOrFail($request->plan_id); if ($user->is_trial || $plan->is_trial !== 'on') { return back()->with('error', __('Trial not available')); } $user->update([ 'plan_id' => $plan->id, 'is_trial' => 1, 'trial_day' => $plan->trial_day, 'trial_expire_date' => now()->addDays($plan->trial_day) ]); return back()->with('success', __('Trial started successfully')); } public function subscribe(Request $request) { $request->validate([ 'plan_id' => 'required|exists:plans,id', 'billing_cycle' => 'required|in:monthly,yearly' ]); $user = auth()->user(); $plan = Plan::findOrFail($request->plan_id); $price = $request->billing_cycle === 'yearly' ? $plan->yearly_price : $plan->price; \App\Models\PlanOrder::create([ 'user_id' => $user->id, 'plan_id' => $plan->id, 'original_price' => $price, 'final_price' => $price, 'status' => 'pending' ]); return back()->with('success', __('Subscription request submitted successfully')); } }