error('ProvisionHostingAccountJob failed', [ 'order_item_id' => $item->id, 'reason' => $reason, ]); $service = Service::where('order_item_id', $item->id)->first(); Service::where('order_item_id', $item->id) ->whereIn('status', ['pending', 'provisioning']) ->update(['status' => 'failed']); if ($service) { $this->activity->log('provision_failed', 'service', 'Khởi tạo hosting thất bại — ' . $reason, $service); } $refunded = $this->refund->refund($item, $reason); $this->notifyAdmin($item, $reason, $refunded); $this->notifyCustomer($item); } public function serverFailedOver(OrderItem $item, DnsServer $server, string $error): void { Log::channel('Custom')->warning('ProvisionHostingAccountJob server failed over', [ 'order_item_id' => $item->id, 'server_id' => $server->id, 'error' => $error, ]); $this->telegram->SendErrorMessage([ 'job' => 'ProvisionHostingAccountJob', 'title' => 'Server Plesk lỗi, chuyển sang server dự phòng', 'order' => $item->order?->order_num, 'domain' => $item->server_name, 'server' => "{$server->name} ({$server->ip_address})", 'error' => $error, ]); } private function notifyAdmin(OrderItem $item, string $reason, bool $refunded): void { $order = $item->order; $this->telegram->SendErrorMessage([ 'job' => 'ProvisionHostingAccountJob', 'title' => 'Khởi tạo hosting thất bại', 'order' => $order?->order_num, 'domain' => $item->server_name, 'customer' => $order?->customer?->email, 'error' => $reason, 'refunded' => $refunded ? 'đã hoàn tiền tự động' : 'chưa hoàn tiền, cần xử lý thủ công', ]); } private function notifyCustomer(OrderItem $item): void { try { $order = $item->order; $customer = $order->customer; VMCreationFailedJob::dispatch([ 'customer_email' => $customer->email, 'customer_name' => (string) $customer->fullname, 'product_name' => $item->getProductAttribute()?->name ?? 'Hosting', 'order_id' => $order->id, 'order_num' => $order->order_num, 'order_item_id' => $item->id, ]); } catch (Throwable $e) { Log::error('HostingProvisionFailure: cannot dispatch failure email: ' . $e->getMessage()); } } }