83 lines
2.7 KiB
PHP
83 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use App\Models\ActivityLog;
|
|
use App\Models\Service;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class DomainServiceSummary
|
|
{
|
|
public const DUE_WITHIN_DAYS = 30;
|
|
public const RECENT_RENEWAL_DAYS = 30;
|
|
private const YEAR_CYCLES = [12, 24, 36];
|
|
|
|
/**
|
|
* @param Collection<int, \App\Models\DnsDomain> $domains
|
|
* @return array<string, array<string, mixed>>
|
|
*/
|
|
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';
|
|
}
|
|
}
|