Files
portal-api/app/Support/DomainServiceSummary.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';
}
}