$domains * @return array> */ public static function forDomains(Collection $domains): array { $keys = $domains->map(fn ($d) => self::key($d->domain_name))->unique()->values()->all(); if (!$keys) { return []; } $services = Service::query() ->with('orderItem:id,months') ->where('type', 'domain') ->whereIn(\DB::raw('LOWER(TRIM(server_name))'), $keys) ->orderByRaw("status = 'cancelled'") ->orderBy('id') ->get() ->unique(fn (Service $s) => self::key($s->server_name)); $lastRenewal = ActivityLog::query() ->where('subject_type', Service::class) ->where('event', 'renewed') ->whereIn('subject_id', $services->pluck('id')) ->selectRaw('subject_id, MAX(created_at) as last_at') ->groupBy('subject_id') ->pluck('last_at', 'subject_id'); return $services->mapWithKeys(fn (Service $s) => [ self::key($s->server_name) => self::summarize($s, $lastRenewal[$s->id] ?? null), ])->all(); } public static function key(?string $name): string { return mb_strtolower(trim((string) $name)); } private static function summarize(Service $service, $lastRenewalAt): array { $months = (int) $service->orderItem?->months; return [ 'service_id' => $service->id, 'service_state' => self::state($service, $lastRenewalAt), 'registered_at' => ($service->started_at ?? $service->created_at)?->toDateString(), 'expires_at' => $service->expires_at?->toDateString(), 'cycle_years' => in_array($months, self::YEAR_CYCLES, true) ? intdiv($months, 12) : null, ]; } private static function state(Service $service, $lastRenewalAt): string { if ($service->status === 'cancelled' || $service->cancelled_at) { return 'cancelled'; } if ($service->expires_at && $service->expires_at->lte(now()->addDays(self::DUE_WITHIN_DAYS))) { return 'due'; } if (!$lastRenewalAt) { return 'new'; } return now()->parse($lastRenewalAt)->gte(now()->subDays(self::RECENT_RENEWAL_DAYS)) ? 'recently_renewed' : 'renewed'; } }