$b['score'] ?: strcasecmp($a['client'], $b['client']); });
$rows = $gaps_only ? array_values(array_filter($all, function ($c) { return $c['missing']; })) : $all;
// How many clients miss each check
$missing_counts = array_fill_keys(array_keys($checks), 0);
foreach ($all as $client) {
foreach ($client['missing'] as $key) {
$missing_counts[$key]++;
}
}
arsort($missing_counts);
$columns = [
'client' => ['label' => 'Client', 'html' => function ($row) {
return reportClientCell($row['client_id'], $row['client'], $row['abbr']);
}],
'score' => ['label' => 'Coverage', 'type' => 'percent', 'html' => function ($row) {
$tone = $row['score'] >= 90 ? 'success' : ($row['score'] >= 70 ? 'warning' : 'danger');
return '
'As of ' . date('M j, Y'),
'controls' => reportSwitchControl('gaps', $gaps_only, 'Only clients with gaps'),
]); ?>
= reportStats([
['label' => 'Active clients', 'value' => reportCount(count($all)), 'sub' => reportCount(count($checks)) . '
checks each'],
['label' => 'Average coverage', 'value_html' => $average === null ? '-' : reportRateHtml($average, 90, 70)],
['label' => 'Fully documented', 'value' => reportCount($complete), 'tone' => $complete ? 'success' : '',
'sub' => count($all) ? reportPercent(reportShare($complete, count($all), 0)) . '
of clients' : ''],
['label' => 'Most often missing', 'value' => $top_gap ? $checks[$top_gap]['label'] : 'Nothing', 'tone' => $top_gap ? 'warning' : 'success',
'sub' => $top_gap ? reportCount($missing_counts[$top_gap]) . '
' . ($missing_counts[$top_gap] === 1 ? 'client' : 'clients') . '' : ''],
]) ?>
= reportSectionOpen('What is missing most', 'Clients without it') ?>
= reportChart([
'type' => 'bar',
'horizontal' => true,
'labels' => array_map(function ($key) use ($checks) { return $checks[$key]['label']; }, array_keys($gap_rows)),
'series' => [['label' => 'Clients without it', 'data' => array_values($gap_rows), 'tone' => 'warning']],
'format' => 'count',
'legend' => false,
], '', 'How many clients are missing each item') ?>
= reportSectionOpen('By client', 'Least covered first') ?>
= reportTable($columns, $rows, ['empty' => reportEmpty($gaps_only ? 'Every client has everything documented.' : 'No active clients.')]) ?>
Active clients, counting only what is not archived. Placed and owned pass at = REPORT_COVERAGE_SHARE ?>%: assets with a location, and laptops, desktops, phones and
tablets with a contact; a client without any is not scored on them. Each missing item opens the page to add it on.