$process * @param array> $candidates * @param array $clarifications * @return array */ public function build(array $process, array $candidates, array $clarifications, bool $financeVisible, bool $contractVisible): array { $claims = []; $add = function (string $id, string $text, string $href, string $label, string $pointer, mixed $basis) use (&$claims): void { $claims[] = ['id' => $id, 'text' => $text, 'source' => ['label' => $label, 'href' => $href, 'pointer' => $pointer], 'basis_sha256' => hash('sha256', json_encode($basis, JSON_THROW_ON_ERROR))]; }; $rules = $process['rules']; $add('rules', count($rules['criteria']).' critérios preservados; mínimo de '.$rules['minimum_reviews'].' avaliações independentes por candidatura. Estes requisitos não comprovam que todas as avaliações já foram feitas.', '#people-report-scope', 'Âmbito e critérios preservados', 'process.rules', $rules); $frozen = $process['selection'] !== null && in_array($process['status'], ['selection_review', 'selected', 'contract_draft'], true); $rows = $frozen ? $process['selection']['rows'] : $candidates; $add('candidates', count($rows).' candidaturas constam da '.($frozen ? 'base de selecção preservada apresentada no relatório.' : 'matriz actual apresentada no relatório.').' A pontuação não constitui selecção automática.', '#people-report-candidates', 'Candidaturas e avaliação', $frozen ? 'process.selection.rows' : 'candidates', $rows); if ($process['selection'] !== null) { $approved = in_array($process['status'], ['selected', 'contract_draft'], true); $text = $approved ? 'Existe uma selecção aprovada e preservada; não equivale a contrato assinado ou admissão efectiva.' : ($process['status'] === 'selection_review' ? 'Existe uma proposta de selecção pendente de conferência independente.' : 'A proposta de selecção foi devolvida para nova análise; não está aprovada.'); $add('selection', $text, '#people-report-selection', 'Fundamento da selecção', 'process.selection', [$process['status'], $process['selection']]); } if ($contractVisible && $process['contract'] !== null) { $add('contract', 'Consta uma minuta contratual de preparação interna, sem confirmação de assinatura ou admissão efectiva.', '#people-report-contract', 'Minuta contratual', 'process.contract', $process['contract']); } if ($clarifications['ready']) { $pending = count(array_filter($clarifications['items'], fn ($item) => $item['status'] !== 'resolved')); $add('clarifications', $pending.' esclarecimentos em acompanhamento constam deste painel. O acompanhamento posterior não reescreve as avaliações originais nem a base de uma selecção aprovada.', '#people-clarifications', 'Esclarecimentos das avaliações', 'clarifications.items', $clarifications['items']); } $basis = ['method' => 'people_evidence_brief_v1', 'process_id' => $process['id'], 'process_version' => $process['version'], 'claims' => $claims]; return [...$basis, 'generated_at' => now()->toIso8601String(), 'basis_sha256' => hash('sha256', json_encode($basis, JSON_THROW_ON_ERROR)), 'finance_visible' => $financeVisible]; } }