diff --git a/app/Http/Controllers/Api/Admin/Customer/CustomerController.php b/app/Http/Controllers/Api/Admin/Customer/CustomerController.php index 9e78190..dea478d 100644 --- a/app/Http/Controllers/Api/Admin/Customer/CustomerController.php +++ b/app/Http/Controllers/Api/Admin/Customer/CustomerController.php @@ -1151,6 +1151,11 @@ class CustomerController extends Controller 'price' => $basePrice, ]); + // Ngày bắt đầu/hết hạn dùng chung cho cả module_vmware (next_due_date/next_invoice) và services. + $startedAt = $data['started_at'] ?? now(); + $expiresAt = $data['expires_at'] + ?? \Carbon\Carbon::parse($startedAt)->addMonths($months); + // 2) ModuleVmware: snapshot từ virtual_machines. `order_id` phải trỏ về // order vừa tạo — client console-ticket/rebuild resolve VM qua // service->orderItem->order->vmWare, không qua services.vm_id. @@ -1181,6 +1186,10 @@ class CustomerController extends Controller 'plain_password' => $data['vm_password'] ?? null, 'port' => $data['vm_port'] ?? null, 'status' => 1, + 'first_payment' => $basePrice, + 'next_payment' => $basePrice, + 'next_due_date' => \Carbon\Carbon::parse($expiresAt)->timestamp, + 'next_invoice' => \Carbon\Carbon::parse($expiresAt)->timestamp, ] ); $vmId = $moduleVm->id; @@ -1234,10 +1243,6 @@ class CustomerController extends Controller ]); // 5) Service — updateOrCreate để tránh trùng khi cùng VM được gán lại - $startedAt = $data['started_at'] ?? now(); - $expiresAt = $data['expires_at'] - ?? \Carbon\Carbon::parse($startedAt)->addMonths($months); - $serviceLookup = $vmId ? ['customer_id' => $customer->id, 'vm_id' => $vmId] : [ @@ -1264,6 +1269,11 @@ class CustomerController extends Controller ] ); + // module_vmware.service_id chỉ biết được sau khi Service đã tồn tại. + if ($vmId) { + \App\Models\ModuleVmware::where('id', $vmId)->update(['service_id' => $service->id]); + } + DB::commit(); return response()->json([ 'error' => false, diff --git a/app/Http/Resources/Api/Client/Service/ServiceClientDetailResource.php b/app/Http/Resources/Api/Client/Service/ServiceClientDetailResource.php index feb8804..2181673 100644 --- a/app/Http/Resources/Api/Client/Service/ServiceClientDetailResource.php +++ b/app/Http/Resources/Api/Client/Service/ServiceClientDetailResource.php @@ -12,8 +12,17 @@ class ServiceClientDetailResource extends JsonResource * * @return array */ - private function resolveSpecs($product): ?array + private function resolveSpecs($vm, $product): ?array { + if ($vm && ($vm->cpu !== null || $vm->ram_mb !== null || $vm->disk_gb !== null)) { + return [ + 'cpu' => (int) ($vm->cpu ?? 0), + 'ram' => (int) ($vm->ram_mb ?? 0), + 'disk' => (int) ($vm->disk_gb ?? 0), + 'bandwidth' => (int) ($product->bandwidth ?? 0), + ]; + } + $addons = $this->addons ?? collect(); if ($addons->isNotEmpty()) { return [ @@ -51,10 +60,10 @@ class ServiceClientDetailResource extends JsonResource 'started_at' => $this->started_at?->toISOString(), 'expires_at' => $this->expires_at?->toISOString(), 'os' => [ - 'version' => $orderItem?->os?->version, - 'group' => $orderItem?->os?->osGroup?->name, + 'version' => $orderItem?->os?->version ?? $vm?->os?->version, + 'group' => $orderItem?->os?->osGroup?->name ?? $vm?->os?->osGroup?->name, ], - 'specs' => $this->resolveSpecs($product), + 'specs' => $this->resolveSpecs($vm, $product), 'order' => $order ? [ 'total' => (float) $order->total, 'months' => (int) $orderItem->months, @@ -63,7 +72,7 @@ class ServiceClientDetailResource extends JsonResource 'vm' => $vm ? [ 'id' => $vm->id, 'vmware_id' => $vm->vmware_id, - 'ip_address' => $vm->ipAddress?->ip, + 'ip_address' => $vm->ipAddress?->ip ?? $vm->ip, 'hostname' => $vm->hostname, 'username' => $vm->user, 'password' => $vm->plain_password ?? null, diff --git a/storage/app/public/payment-proofs/n0qMlt5cfhodyib9oSJq0cGOLuK1oPBDf8Um9SA1.png b/storage/app/public/payment-proofs/n0qMlt5cfhodyib9oSJq0cGOLuK1oPBDf8Um9SA1.png new file mode 100644 index 0000000..8c2dc62 Binary files /dev/null and b/storage/app/public/payment-proofs/n0qMlt5cfhodyib9oSJq0cGOLuK1oPBDf8Um9SA1.png differ