serviceClientService = $serviceClientService; $this->serviceClientRepository = $serviceClientRepository; $this->activityLogger = $activityLogger; } public function indexVps(Request $request): JsonResponse { $perPage = min((int) $request->get('per_page', 15), 100); $customer = $request->user(); $services = $this->serviceClientService->getActiveServices($customer->id, 'vps', $perPage); return (new VpsServiceCollection($services)) ->additional([ 'error' => false, 'message' => 'Lấy dữ liệu thành công', 'page_type' => 'service_vps', ]) ->response(); } public function indexHosting(Request $request): JsonResponse { $perPage = min((int) $request->get('per_page', 15), 100); return response()->json([ 'error' => false, 'message' => 'Lấy dữ liệu thành công', 'page_type' => 'service_hosting', 'data' => [ 'items' => [], 'pagination' => [ 'total' => 0, 'per_page' => $perPage, 'current_page' => 1, 'last_page' => 1, ], ], ]); } public function indexWebDesign(Request $request): JsonResponse { $perPage = min((int) $request->get('per_page', 15), 100); return response()->json([ 'error' => false, 'message' => 'Lấy dữ liệu thành công', 'page_type' => 'service_web_design', 'data' => [ 'items' => [], 'pagination' => [ 'total' => 0, 'per_page' => $perPage, 'current_page' => 1, 'last_page' => 1, ], ], ]); } public function getDetail(Request $request, string $uuid) { $service = $this->serviceClientService->getDetailService($uuid, $request->user()->id); if (!$service) { return response()->json( [ 'error' => true, 'message' => 'Không tìm thấy dịch vụ', ], 404, ); } return (new ServiceClientDetailResource($service))->additional([ 'error' => false, 'message' => 'Lấy dữ liệu thành công', 'page_type' => 'service', ]); } public function getConsoleTicket(Request $request, string $uuid, vCenter $serviceVCenter) { $customer = $request->user(); $service = Service::with(['orderItem.order.vmWare.vCenter']) ->where('uuid', $uuid) ->where('customer_id', $customer->id) ->first(); if (!$service) { return response()->json(['error' => true, 'message' => 'Không tìm thấy dịch vụ'], 404); } $vm = $service->orderItem?->order?->vmWare?->first(); if (!$vm) { return response()->json(['error' => true, 'message' => 'Dịch vụ chưa được cấp phát VM'], 404); } $vcenter = $vm->vCenter; if (!$vcenter) { return response()->json(['error' => true, 'message' => 'Không tìm thấy thông tin vCenter'], 404); } if (!$serviceVCenter->loginServer($vcenter)) { return response()->json(['error' => true, 'message' => 'Không thể đăng nhập vào vCenter']); } $consoleTicket = $serviceVCenter->GetConsoleTickets($vm->vmware_id); if ($consoleTicket === 'Login_Again') { if ($serviceVCenter->loginServer($vcenter)) { $consoleTicket = $serviceVCenter->GetConsoleTickets($vm->vmware_id); } else { return response()->json(['error' => true, 'message' => 'Không thể đăng nhập lại vào vCenter']); } } if (is_string($consoleTicket)) { return response()->json(['error' => true, 'message' => "Failed to get console ticket: $consoleTicket"]); } if ($consoleTicket['error']) { return response()->json(['error' => true, 'message' => $consoleTicket['data']]); } $this->activityLogger->log( event: 'console_access', logName: 'VM', description: "Customer {$customer->email} truy cập console VM: {$vm->name} (service: {$uuid})", subject: $vm, newValues: ['service_uuid' => $uuid, 'vm_name' => $vm->name], ); return response()->json([ 'error' => false, 'ticket' => $consoleTicket['data']['ticket'], 'host' => $consoleTicket['data']['host'], ]); } public function getTicketByOrderNum(Request $request, vCenter $serviceVCenter): JsonResponse { $orderNum = (string) $request->query('order_num', ''); if ($orderNum === '') { return response()->json(['error' => true, 'message' => 'Thiếu order_num'], 422); } $customer = $request->user(); $order = Order::with(['vmWare.vCenter']) ->where('customer_id', $customer->id) ->where('order_num', $orderNum) ->first(); if (!$order) { return response()->json(['error' => true, 'message' => 'Không tìm thấy đơn hàng'], 404); } $vm = $order->vmWare->first(); if (!$vm) { return response()->json(['error' => true, 'message' => 'Đơn hàng chưa có VM'], 404); } $vcenter = $vm->vCenter; if (!$vcenter) { return response()->json(['error' => true, 'message' => 'Không tìm thấy thông tin vCenter'], 404); } if (!$serviceVCenter->loginServer($vcenter)) { return response()->json(['error' => true, 'message' => 'Không thể đăng nhập vào vCenter']); } $consoleTicket = $serviceVCenter->GetConsoleTickets($vm->vmware_id); if ($consoleTicket === 'Login_Again') { if ($serviceVCenter->loginServer($vcenter)) { $consoleTicket = $serviceVCenter->GetConsoleTickets($vm->vmware_id); } else { return response()->json(['error' => true, 'message' => 'Không thể đăng nhập lại vào vCenter']); } } if (is_string($consoleTicket)) { return response()->json(['error' => true, 'message' => "Failed to get console ticket: $consoleTicket"]); } if ($consoleTicket['error']) { return response()->json(['error' => true, 'message' => $consoleTicket['data']]); } $this->activityLogger->log( event: 'console_access', logName: 'VM', description: "Customer {$customer->email} truy cập console VM: {$vm->name} (order: {$order->order_num})", subject: $vm, newValues: ['order_num' => $order->order_num, 'vm_name' => $vm->name], ); return response()->json([ 'error' => false, 'ticket' => $consoleTicket['data']['ticket'], 'host' => $consoleTicket['data']['host'], 'order_num' => $order->order_num, 'vm_id' => $vm->id, ]); } public function getAvailableOs(Request $request, string $uuid): JsonResponse { $customer = $request->user(); $service = Service::with([ 'product.osVersions' => fn($q) => $q->where('status', 1)->with('osGroup'), ]) ->where('uuid', $uuid) ->where('customer_id', $customer->id) ->first(); if (!$service) { return response()->json(['success' => false, 'message' => 'Không tìm thấy dịch vụ'], 404); } if (!in_array($service->status, ['active', 'suspended'], true)) { return response()->json( ['success' => false, 'message' => 'Dịch vụ không ở trạng thái hợp lệ để xem OS'], 422, ); } if (!$service->product) { return response()->json(['success' => false, 'message' => 'Không tìm thấy product của dịch vụ'], 404); } $grouped = $service->product->osVersions ->groupBy(fn($os) => $os->osGroup?->id ?? 0) ->map( fn($items) => [ 'group' => [ 'id' => $items->first()->osGroup?->id, 'name' => $items->first()->osGroup?->name, 'thumbnail' => $items->first()->osGroup?->thumbnail, ], 'items' => $items ->map( fn($os) => [ 'id' => $os->id, 'version' => $os->version, 'template_id' => $os->template_id, ], ) ->values(), ], ) ->values(); return response()->json([ 'success' => true, 'data' => $grouped, ]); } public function updateAutoRenew(Request $request, string $uuid): JsonResponse { $validated = $request->validate(['auto_renew' => ['required', 'boolean']]); $service = Service::query() ->where('uuid', $uuid) ->where('customer_id', $request->user()->id) ->first(); if (! $service) { return response()->json(['error' => true, 'message' => 'Không tìm thấy dịch vụ'], 404); } $service->update(['auto_renew' => (bool) $validated['auto_renew']]); $this->activityLogger->log( event: 'updated', logName: 'Service', description: "Customer {$request->user()->email} " . ($validated['auto_renew'] ? 'bật' : 'tắt') . " tự động gia hạn dịch vụ #{$service->id}", subject: $service, newValues: ['auto_renew' => (bool) $validated['auto_renew']], ); return response()->json([ 'error' => false, 'message' => 'Cập nhật tự động gia hạn thành công.', 'data' => [ 'uuid' => $service->uuid, 'id' => $service->id, 'auto_renew' => (bool) $service->auto_renew, ], ]); } public function rebuild(Request $request, string $uuid, VmRebuildService $rebuildService): JsonResponse { $customer = $request->user(); $payload = $request->validate([ 'os_id' => ['required', 'integer', 'exists:os,id'], 'password' => ['nullable', 'string', 'min:8', 'max:255'], ]); $service = Service::with(['product.osVersions', 'vmware']) ->where('uuid', $uuid) ->where('customer_id', $customer->id) ->first(); if (!$service) { return response()->json(['success' => false, 'message' => 'Không tìm thấy dịch vụ'], 404); } if ($service->status === 'suspended') { return response()->json( ['success' => false, 'message' => 'Dịch vụ đang bị tạm ngưng, không thể rebuild'], 422, ); } if (!$service->isActive()) { return response()->json(['success' => false, 'message' => 'Dịch vụ không ở trạng thái active'], 422); } $allowedOsIds = $service->product?->osVersions()->where('status', 1)->pluck('os.id')->map('intval')->toArray() ?? []; if (!in_array((int) $payload['os_id'], $allowedOsIds, true)) { return response()->json(['success' => false, 'message' => 'OS không hợp lệ cho sản phẩm hiện tại'], 422); } $vm = $service->vmware; if (!$vm) { return response()->json(['success' => false, 'message' => 'Dịch vụ chưa được cấp phát VM'], 404); } try { $log = $rebuildService->dispatchRebuild( moduleVmwareId: (int) $vm->id, newOsId: (int) $payload['os_id'], initiatorCustomerId: (int) $customer->id, customPassword: !empty($payload['password']) ? (string) $payload['password'] : null, initiator: 'client', note: 'Client rebuild via service UUID: ' . $uuid, ); } catch (Throwable $e) { Log::error('Client rebuild dispatch failed', [ 'service_uuid' => $uuid, 'module_vmware_id' => $vm->id, 'error' => $e->getMessage(), ]); return response()->json([ 'success' => false, 'message' => 'Không thể gửi yêu cầu rebuild: ' . $e->getMessage(), ], 400); } $this->activityLogger->log( event: 'rebuild', logName: 'VM', description: "Customer {$customer->email} rebuild VM: {$vm->name} với OS ID: {$payload['os_id']} qua service UUID: {$uuid}", subject: $vm, newValues: [ 'os_id' => (int) $payload['os_id'], 'service_uuid' => $uuid, 'reinstall_log_id' => $log->id, 'custom_password' => !empty($payload['password']), ], ); return response()->json([ 'success' => true, 'message' => 'Đã gửi yêu cầu rebuild VM', 'data' => [ 'reinstall_log_id' => $log->id, 'status' => $log->status, ], ]); } }