$this->id, 'order_num' => $this->order_num, 'duplicate' => BillingDuplicateDetector::forOrder($this->id), 'customer' => $this->whenLoaded('customer', fn() => [ 'id' => $this->customer->id, 'uuid' => $this->customer->uuid, 'fullname' => $this->customer->fullname, 'email' => $this->customer->email, 'phone' => $this->customer->phone ?? null, ]), 'user' => $this->whenLoaded('user', fn() => [ 'id' => $this->user->id, 'fullname' => $this->user->fullname, 'email' => $this->user->email, ]), 'payment' => $this->whenLoaded('payment', fn() => [ 'id' => $this->payment->id, 'name' => $this->payment->name, 'type' => $this->payment->type, ]), 'discount' => $this->whenLoaded('discount', fn() => [ 'id' => $this->discount->id, 'code' => $this->discount->code, 'value' => $this->discount->value, ]), 'invoice' => $this->whenLoaded('invoice', fn() => [ 'id' => $this->invoice->id, 'invoice_number' => $this->invoice->invoice_number, 'sub_total' => $this->invoice->sub_total, 'discount_amount' => $this->invoice->discount_amount, 'tax' => $this->invoice->tax, 'total' => $this->invoice->total, 'status' => $this->invoice->status, 'date' => $this->invoice->created_at, 'due_date' => $this->invoice->due_date, 'date_paid' => $this->invoice->paid_at, ]), // An order can have many invoices (1 initial + N renewals) — this is the full list. 'invoices' => $this->whenLoaded('invoices', fn() => $this->invoices->map(fn($invoice) => [ 'id' => $invoice->id, 'invoice_number' => $invoice->invoice_number, 'invoice_type' => $invoice->invoice_type, 'sub_total' => $invoice->sub_total, 'discount_amount' => $invoice->discount_amount, 'tax' => $invoice->tax, 'total' => $invoice->total, 'amount_paid' => (int) $invoice->amount_paid, 'outstanding' => \App\Services\InvoicePaymentService::outstanding($invoice), 'status' => $invoice->status, 'date' => $invoice->created_at, 'due_date' => $invoice->due_date, 'date_paid' => $invoice->paid_at, 'reminder_step' => (int) $invoice->reminder_step, 'billing_period_start' => $invoice->billing_period_start, 'billing_period_end' => $invoice->billing_period_end, 'payment_method' => $invoice->payment?->name ?? $invoice->payment_method, 'note' => $invoice->note, 'attachments' => $invoice->relationLoaded('attachments') ? $invoice->attachments->map(fn($attachment) => [ 'id' => $attachment->id, 'type' => $attachment->type, 'filename' => $attachment->filename, 'url' => $attachment->url, 'mime_type' => $attachment->mime_type, 'size' => $attachment->size, 'uploaded_by' => $attachment->uploaded_by, 'created_at' => $attachment->created_at, ]) : [], // Which service(s)/product(s) this invoice actually bills for — without this, // an invoice was a black box: just a total with no visible line items. 'items' => $invoice->relationLoaded('invoiceItems') ? $invoice->invoiceItems->map(fn($item) => [ 'id' => $item->id, 'product_id' => $item->product_id, 'product_name' => $item->product?->name, 'product_type' => $item->product?->product_type, 'type' => $item->type, 'description' => $item->description, 'months' => $item->months, 'quantity' => $item->quantity, 'unit_price' => $item->unit_price, 'total_price' => $item->total_price, ]) : [], ])), 'sub_total' => $this->sub_total, 'discount_amount' => $this->discount_amount, 'coupon_code' => $this->coupon_code, 'total' => $this->total, // Order has no payment_id FK — `payment` relation is always null. Fall back to // the raw payment_method string instead of letting whenLoaded() mask it with null. 'payment_method' => $this->payment?->name ?? $this->payment_method, 'payment_proof' => $this->payment_proof, 'note' => $this->note, 'client_ip' => $this->client_ip, 'status' => $this->status, 'is_starred' => (bool) $this->is_starred, 'tags' => $this->whenLoaded('tags'), 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, 'vmwares' => $this->whenLoaded('moduleVmwares', fn() => $this->moduleVmwares->map(fn($vm) => [ 'id' => $vm->id, 'vmware_id' => $vm->vmware_id, 'name' => $vm->name, 'hostname' => $vm->hostname, 'user' => $vm->user, 'ip' => $vm->ipAddress?->ip, 'os_id' => $vm->os_id, 'status' => $vm->status, 'next_due_date' => $vm->next_due_date, ])), 'order_items' => $this->whenLoaded('orderItems', fn() => $this->orderItems->map(fn($item) => [ ...OrderItemServiceResource::make($item)->resolve(), 'os' => $item->os ? [ 'id' => $item->os->id, 'name' => $item->os->name, 'version' => $item->os->version, ] : null, 'billing_cycle' => $item->billing_cycle, 'months' => $item->months, 'expiry_date' => $item->expiry_date, 'quantity' => $item->quantity, 'price' => $item->price, ])), ]; } }