$rows */ public function __construct( public int $tenantId, public ?OperationRun $basisRun, public bool $hasCurrentCoverageResult, public int $supportedTypeCount, public int $succeededTypeCount, public int $failedTypeCount, public int $skippedTypeCount, public int $unknownTypeCount, public int $followUpTypeCount, public int $observedItemTotal, public array $rows, ) { if ($this->tenantId <= 0) { throw new InvalidArgumentException('Tenant coverage truth requires a positive tenant id.'); } if ($this->supportedTypeCount < 0 || $this->observedItemTotal < 0) { throw new InvalidArgumentException('Tenant coverage truth counts must be zero or greater.'); } } public function basisRunId(): ?int { return $this->basisRun instanceof OperationRun ? (int) $this->basisRun->getKey() : null; } public function basisRunOutcome(): ?string { return $this->basisRun instanceof OperationRun ? (string) $this->basisRun->outcome : null; } public function basisCompletedAtLabel(): ?string { if (! $this->basisRun instanceof OperationRun) { return null; } $timestamp = $this->basisRun->completed_at ?? $this->basisRun->started_at ?? $this->basisRun->created_at; return $timestamp?->diffForHumans(['short' => true]); } public function topPriorityFollowUpRow(): ?TenantCoverageTypeTruth { foreach ($this->rows as $row) { if ($row->followUpRequired) { return $row; } } return null; } public function observedTypeCount(): int { return count(array_filter( $this->rows, static fn (TenantCoverageTypeTruth $row): bool => $row->observedItemCount > 0, )); } /** * @return list */ public function followUpRows(): array { return array_values(array_filter( $this->rows, static fn (TenantCoverageTypeTruth $row): bool => $row->followUpRequired, )); } /** * @return array{ * tenantId: int, * basisRun: array{id: int, outcome: string, completedAt: string|null}|null, * hasCurrentCoverageResult: bool, * summary: array{ * supportedTypes: int, * succeededTypes: int, * failedTypes: int, * skippedTypes: int, * unknownTypes: int, * followUpTypes: int, * observedItems: int * }, * rows: list> * } */ public function toArray(): array { return [ 'tenantId' => $this->tenantId, 'basisRun' => $this->basisRun instanceof OperationRun ? [ 'id' => (int) $this->basisRun->getKey(), 'outcome' => (string) $this->basisRun->outcome, 'completedAt' => $this->basisRun->completed_at?->toIso8601String(), ] : null, 'hasCurrentCoverageResult' => $this->hasCurrentCoverageResult, 'summary' => [ 'supportedTypes' => $this->supportedTypeCount, 'succeededTypes' => $this->succeededTypeCount, 'failedTypes' => $this->failedTypeCount, 'skippedTypes' => $this->skippedTypeCount, 'unknownTypes' => $this->unknownTypeCount, 'followUpTypes' => $this->followUpTypeCount, 'observedItems' => $this->observedItemTotal, ], 'rows' => array_map( static fn (TenantCoverageTypeTruth $row): array => $row->toArray(), $this->rows, ), ]; } }