namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\Service; use App\Models\Category; use App\Models\ApiProvider; use Illuminate\Http\Request; use Illuminate\Support\Str; use Illuminate\Support\Facades\DB; class ServiceController extends Controller { public function index(Request $request) { $query = Service::with(['category', 'apiProvider']); // Search if ($request->has('search')) { $search = $request->search; $query->where(function($q) use ($search) { $q->where('name', 'like', "%{$search}%") ->orWhere('description', 'like', "%{$search}%") ->orWhere('api_service_id', 'like', "%{$search}%"); }); } // Filter by category if ($request->has('category') && $request->category != 'all') { $query->where('category_id', $request->category); } // Filter by provider if ($request->has('provider') && $request->provider != 'all') { $query->where('api_provider_id', $request->provider); } // Filter by status if ($request->has('status') && $request->status != 'all') { $query->where('status', $request->status); } $services = $query->orderBy('created_at', 'desc')->paginate(20); $categories = Category::where('status', 'active')->orderBy('name')->get(); $providers = ApiProvider::where('status', 'active')->orderBy('name')->get(); $stats = [ 'total' => Service::count(), 'active' => Service::where('status', 'active')->count(), 'inactive' => Service::where('status', 'inactive')->count(), 'api_services' => Service::whereNotNull('api_provider_id')->count(), ]; return view('admin.services.index', compact('services', 'categories', 'providers', 'stats')); } public function create() { $categories = Category::where('status', 'active')->orderBy('name')->get(); $providers = ApiProvider::where('status', 'active')->orderBy('name')->get(); return view('admin.services.create', compact('categories', 'providers')); } public function store(Request $request) { $request->validate([ 'category_id' => 'required|exists:categories,id', 'name' => 'required|string|max:255', 'slug' => 'nullable|string|max:255|unique:services', 'description' => 'nullable|string', 'price' => 'required|numeric|min:0', 'original_price' => 'nullable|numeric|min:0', 'min_order' => 'required|integer|min:1', 'max_order' => 'nullable|integer|min:1', 'service_type' => 'required|in:default,custom_comments,package,subscription', 'api_provider_id' => 'nullable|exists:api_providers,id', 'api_service_id' => 'nullable|string|max:100', 'profit_type' => 'required|in:fixed,percentage', 'profit_value' => 'required|numeric|min:0', 'required_fields' => 'nullable|array', 'tags' => 'nullable|string', 'image' => 'nullable|image|max:2048', 'status' => 'required|in:active,inactive,maintenance', 'is_featured' => 'boolean', 'is_hidden' => 'boolean', 'sort_order' => 'nullable|integer', 'processing_time' => 'nullable|string|max:100', 'refill_possible' => 'boolean', 'cancel_possible' => 'boolean', ]); $data = $request->except(['image', 'required_fields']); // Generate slug if not provided if (empty($data['slug'])) { $data['slug'] = Str::slug($request->name); } // Handle required fields if ($request->has('required_fields')) { $data['required_fields'] = json_encode($request->required_fields); } // Handle image if ($request->hasFile('image')) { $path = $request->file('image')->store('services', 'public'); $data['image'] = $path; } // Calculate profit margin $data['profit_margin'] = $this->calculateProfitMargin($data['price'], $data['profit_type'], $data['profit_value']); $service = Service::create($data); // Log activity auth()->guard('admin')->user()->logActivity( 'Created service: ' . $service->name, ['service_id' => $service->id] ); return redirect()->route('admin.services.index') ->with('success', 'Service created successfully.'); } public function edit(Service $service) { $categories = Category::where('status', 'active')->orderBy('name')->get(); $providers = ApiProvider::where('status', 'active')->orderBy('name')->get(); return view('admin.services.edit', compact('service', 'categories', 'providers')); } public function update(Request $request, Service $service) { $request->validate([ 'category_id' => 'required|exists:categories,id', 'name' => 'required|string|max:255', 'slug' => 'nullable|string|max:255|unique:services,slug,' . $service->id, 'description' => 'nullable|string', 'price' => 'required|numeric|min:0', 'original_price' => 'nullable|numeric|min:0', 'min_order' => 'required|integer|min:1', 'max_order' => 'nullable|integer|min:1', 'service_type' => 'required|in:default,custom_comments,package,subscription', 'api_provider_id' => 'nullable|exists:api_providers,id', 'api_service_id' => 'nullable|string|max:100', 'profit_type' => 'required|in:fixed,percentage', 'profit_value' => 'required|numeric|min:0', 'required_fields' => 'nullable|array', 'tags' => 'nullable|string', 'image' => 'nullable|image|max:2048', 'status' => 'required|in:active,inactive,maintenance', 'is_featured' => 'boolean', 'is_hidden' => 'boolean', 'sort_order' => 'nullable|integer', 'processing_time' => 'nullable|string|max:100', 'refill_possible' => 'boolean', 'cancel_possible' => 'boolean', ]); $data = $request->except(['image', 'required_fields']); // Generate slug if not provided if (empty($data['slug'])) { $data['slug'] = Str::slug($request->name); } // Handle required fields if ($request->has('required_fields')) { $data['required_fields'] = json_encode($request->required_fields); } // Handle image if ($request->hasFile('image')) { // Delete old image if ($service->image) { \Storage::disk('public')->delete($service->image); } $path = $request->file('image')->store('services', 'public'); $data['image'] = $path; } // Calculate profit margin $data['profit_margin'] = $this->calculateProfitMargin($data['price'], $data['profit_type'], $data['profit_value']); $service->update($data); // Log activity auth()->guard('admin')->user()->logActivity( 'Updated service: ' . $service->name, ['service_id' => $service->id] ); return redirect()->route('admin.services.index') ->with('success', 'Service updated successfully.'); } public function destroy(Service $service) { // Check if service has orders if ($service->orders()->exists()) { return back()->with('error', 'Cannot delete service with existing orders.'); } // Delete image if ($service->image) { \Storage::disk('public')->delete($service->image); } $name = $service->name; $service->delete(); // Log activity auth()->guard('admin')->user()->logActivity( 'Deleted service: ' . $name, ['service_id' => $service->id] ); return redirect()->route('admin.services.index') ->with('success', 'Service deleted successfully.'); } public function massUpdate(Request $request) { $request->validate([ 'action' => 'required|in:price_increase,price_decrease,status_change,category_change', 'service_ids' => 'required|array', 'service_ids.*' => 'exists:services,id', ]); $count = count($request->service_ids); $services = Service::whereIn('id', $request->service_ids)->get(); switch ($request->action) { case 'price_increase': $request->validate([ 'percentage' => 'required|numeric|min:0|max:1000', ]); foreach ($services as $service) { $newPrice = $service->price * (1 + $request->percentage / 100); $service->update(['price' => $newPrice]); } $message = "Prices increased by {$request->percentage}% for {$count} services."; break; case 'price_decrease': $request->validate([ 'percentage' => 'required|numeric|min:0|max:100', ]); foreach ($services as $service) { $newPrice = $service->price * (1 - $request->percentage / 100); $service->update(['price' => $newPrice]); } $message = "Prices decreased by {$request->percentage}% for {$count} services."; break; case 'status_change': $request->validate([ 'status' => 'required|in:active,inactive,maintenance', ]); Service::whereIn('id', $request->service_ids) ->update(['status' => $request->status]); $message = "Status changed to {$request->status} for {$count} services."; break; case 'category_change': $request->validate([ 'category_id' => 'required|exists:categories,id', ]); Service::whereIn('id', $request->service_ids) ->update(['category_id' => $request->category_id]); $message = "Category changed for {$count} services."; break; } // Log activity auth()->guard('admin')->user()->logActivity( 'Mass update services: ' . $request->action, ['service_ids' => $request->service_ids, 'count' => $count] ); return back()->with('success', $message); } public function updateProfitMargin(Request $request) { $request->validate([ 'type' => 'required|in:fixed,percentage', 'value' => 'required|numeric|min:0', 'service_ids' => 'required|array', 'service_ids.*' => 'exists:services,id', ]); $services = Service::whereIn('id', $request->service_ids)->get(); $count = 0; foreach ($services as $service) { $service->profit_type = $request->type; $service->profit_value = $request->value; $service->profit_margin = $this->calculateProfitMargin( $service->price, $request->type, $request->value ); $service->save(); $count++; } // Log activity auth()->guard('admin')->user()->logActivity( 'Updated profit margins', ['type' => $request->type, 'value' => $request->value, 'count' => $count] ); return back()->with('success', "Profit margins updated for {$count} services."); } protected function calculateProfitMargin($price, $profitType, $profitValue) { if ($profitType === 'fixed') { return ($profitValue / $price) * 100; } return $profitValue; // Already percentage } public function syncFromProvider(Request $request) { $request->validate([ 'provider_id' => 'required|exists:api_providers,id', ]); $provider = ApiProvider::findOrFail($request->provider_id); // This would trigger API sync // dispatch(new SyncProviderServicesJob($provider)); return back()->with('info', 'Service sync started. This may take a few minutes.'); } }