$this->invoice_number, 'invoice_type' => $this->invoice_type, 'status' => $this->status, 'status_text' => InvoiceStatus::tryFrom((int) $this->status)?->label() ?? '-', 'sub_total' => (float) $this->sub_total, 'discount_amount' => (float) ($this->discount_amount ?? 0), 'tax' => (float) $this->tax, 'total' => (float) $this->total, // Công nợ: đã thu / còn thiếu. Dịch vụ chỉ kích hoạt khi outstanding = 0. 'amount_paid' => (float) $this->amount_paid, 'outstanding' => (float) \App\Services\InvoicePaymentService::outstanding($this->resource), 'payment_method' => $this->resolvePaymentMethod($this->resource), 'auto_renew' => (bool) $this->auto_renew, 'created_at' => $this->created_at?->toISOString(), 'due_date' => $this->due_date?->toISOString(), 'paid_at' => $this->paid_at?->toISOString(), 'customer' => $this->whenLoaded('customer', fn () => [ 'name' => $this->customer->fullname, 'email' => $this->customer->email, 'address' => $this->customer->address, ]), 'order' => $this->whenLoaded('order', fn () => [ 'order_num' => $this->order->order_num, 'total' => (float) $this->order->total, ]), 'items' => $this->whenLoaded('order', fn () => $this->order->orderItems->map(fn ($item) => [ 'product_name' => $item->product?->name, 'server_name' => $item->server_name, 'billing_cycle' => $item->billing_cycle, 'price' => (float) $item->price, 'months' => $item->months, 'os_id' => $item->os_id, ])->values()->all()), 'attachments' => $this->whenLoaded('attachments', fn () => $this->attachments->map(fn ($a) => [ 'filename' => $a->filename, 'url' => $a->url, 'mime_type' => $a->mime_type, ])->all()), 'vmware' => $this->when( $this->order?->relationLoaded('vmWare') && $this->order->vmWare->isNotEmpty(), fn () => $this->resolveVmware($this->order->vmWare->first()), ), ]; } private function resolveVmware(\App\Models\ModuleVmware $vm): array { return [ 'id' => $vm->id, 'uuid' => $vm->service?->uuid, 'name' => $vm->name, 'hostname' => $vm->hostname, 'ip_address' => $vm->ip, 'os_name' => $vm->os?->name, 'status' => $vm->status, 'username' => $vm->user, 'port' => $vm->port, 'power_state' => match ($vm->virtualMachine?->power_state) { 'POWERED_ON' => 'poweredOn', 'POWERED_OFF' => 'poweredOff', 'SUSPENDED' => 'suspended', default => null, }, 'next_due_date' => $vm->next_due_date ? \Illuminate\Support\Carbon::createFromTimestamp($vm->next_due_date)->toISOString() : null, ]; } }