map(fn ($id) => (int) $id)->unique()->values(); $previousCustomerIds = $domain->customer()->pluck('customers.id'); $oldName = $previousDomainName ?? $domain->domain_name; DB::transaction(function () use ($domain, $customerIds, $previousCustomerIds, $oldName): void { $domain->customer()->sync($customerIds->all()); foreach ($customerIds as $customerId) { $service = $this->findService($customerId, $oldName, $domain->domain_name); if ($service?->trashed()) { $service->restore(); } $service ??= new Service([ 'customer_id' => $customerId, 'type' => 'domain', 'note' => self::AUTO_CREATED_NOTE, ]); $service->fill([ 'server_name' => $domain->domain_name, 'status' => $this->serviceStatus($domain), 'started_at' => $service->started_at ?? $domain->created_at ?? Carbon::now(), ])->save(); if ($service->status !== 'cancelled') { $this->orderRecorder->ensureForService($service); } } $removedCustomerIds = $previousCustomerIds->diff($customerIds); if ($removedCustomerIds->isNotEmpty()) { Service::query() ->whereIn('customer_id', $removedCustomerIds) ->where('type', 'domain') ->whereIn(DB::raw('LOWER(TRIM(server_name))'), array_unique([ $this->domainKey($oldName), $this->domainKey($domain->domain_name), ])) ->get() ->each(function (Service $service): void { $this->orderRecorder->cancelUnpaidInvoice($service); $service->delete(); }); } }); } public function updateCustomerDomain( DnsDomain $domain, int $customerId, ?string $expiresAt, ): Service { $this->syncCustomers($domain, $domain->customer()->pluck('customers.id')->all()); $service = $this->findService($customerId, $domain->domain_name, $domain->domain_name); abort_if(! $service, 404, 'Không tìm thấy dịch vụ tên miền'); $service->fill([ 'status' => $this->serviceStatus($domain), 'started_at' => $domain->created_at, 'expires_at' => $expiresAt ? Carbon::parse($expiresAt)->setTimeFrom($service->expires_at ?? Carbon::today()) : null, ])->save(); return $service; } private function findService(int $customerId, string $oldName, string $currentName): ?Service { return Service::withTrashed() ->where('customer_id', $customerId) ->where('type', 'domain') ->whereIn(DB::raw('LOWER(TRIM(server_name))'), array_unique([ $this->domainKey($oldName), $this->domainKey($currentName), ])) ->orderBy('id') ->first(); } private function serviceStatus(DnsDomain $domain): string { return match ((int) $domain->is_created) { DnsDomain::STATUS_CREATED => 'active', DnsDomain::STATUS_INACTIVE => 'suspended', DnsDomain::STATUS_CANCELLED => 'cancelled', default => 'pending', }; } private function domainKey(?string $domainName): string { return mb_strtolower(trim((string) $domainName)); } }