per_page ?? 15), 100); $query = Service::with(['customer:id,uuid,fullname,email', 'product:id,uuid,name', 'invoice:id,invoice_number', 'vmware:id,name,module_ip_address']) ->when($request->filter, fn($q, $v) => $q->where('server_name', 'like', "%{$v}%")) ->when($request->status, fn($q, $v) => $q->where('status', $v)) ->when($request->customer_id, fn($q, $v) => $q->where('customer_id', $v)); $paginator = $query->latest()->paginate($perPage); return response()->json([ 'error' => false, 'data' => [ 'items' => $paginator->items(), 'total' => $paginator->total(), 'per_page' => $paginator->perPage(), 'current_page' => $paginator->currentPage(), 'last_page' => $paginator->lastPage(), ], ]); } public function show(int $id): JsonResponse { $service = Service::with(['customer', 'product', 'orderItem', 'invoice', 'vmware.os.osGroup', 'addons']) ->findOrFail($id); ModuleVmware::resolveVirtualMachineIds([$service->vmware]); return response()->json(['error' => false, 'data' => $service]); } public function detachCustomer(int $id): JsonResponse { $service = Service::findOrFail($id); $service->update(['customer_id' => null]); return response()->json(['error' => false, 'message' => 'Đã gỡ khách hàng khỏi dịch vụ.']); } public function resendCredentials(int $id): JsonResponse { $service = Service::findOrFail($id); abort_if(!$service->vm_id, 422, 'Dịch vụ chưa gắn VM.'); ResendVmCredentialsEmailJob::dispatch($service->vm_id); return response()->json(['error' => false, 'message' => 'Đã xếp hàng gửi lại thông tin VPS cho khách hàng.']); } }