Fix double-counting in VCL multi-vertical stats — use only ALL: rollup rows
The Summary sheet in each vertical spreadsheet contains both sub-team rows (ACCESS-OPS, STEAM, INTELDEV, etc.) AND a rollup row (ALL: NTS-AEO) per metric. The rollup row already includes all sub-team totals, so summing all rows was double-counting every device. Fixed in three places: - GET /stats endpoint: added AND team LIKE 'ALL:%' filter - persistMultiVerticalUpload snapshot creation: only sum ALL: entries - GET /vertical/:code/metrics category aggregation: only use ALL: rows Also ran a one-time data fix to correct existing compliance_snapshots.
This commit is contained in:
@@ -141,17 +141,22 @@ async function persistMultiVerticalUpload({ items, summary, reportDate, filename
|
||||
}
|
||||
|
||||
// 6. Create/update compliance_snapshots for this vertical
|
||||
// Use summary data for accurate totals (compliance_items only has non-compliant devices)
|
||||
// Use summary data for accurate totals (compliance_items only has non-compliant devices).
|
||||
// IMPORTANT: Only use "ALL:" rollup rows to avoid double-counting. Each Summary sheet
|
||||
// has sub-team rows AND a rollup row per metric — the rollup already includes sub-teams.
|
||||
const currentMonth = new Date().toISOString().slice(0, 7);
|
||||
let totalDevices = 0, snapshotCompliant = 0, snapshotNonCompliant = 0;
|
||||
|
||||
if (summary && summary.entries && summary.entries.length > 0) {
|
||||
for (const entry of summary.entries) {
|
||||
// Only count rollup rows (team starts with "ALL:") to avoid double-counting
|
||||
if (entry.team && entry.team.startsWith('ALL:')) {
|
||||
totalDevices += entry.total || 0;
|
||||
snapshotCompliant += entry.compliant || 0;
|
||||
snapshotNonCompliant += entry.non_compliant || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const compPct = totalDevices > 0 ? Math.round((snapshotCompliant / totalDevices) * 100 * 100) / 100 : 0;
|
||||
|
||||
@@ -460,16 +465,18 @@ function createVCLMultiVerticalRouter(upload) {
|
||||
|
||||
const latestUploadIds = latestUploads.map(u => u.id);
|
||||
|
||||
// Aggregate summary data from the latest upload per vertical
|
||||
// Each row in vcl_multi_vertical_summary is one metric for one vertical.
|
||||
// We sum across metrics per vertical to get vertical-level totals.
|
||||
// Aggregate summary data from the latest upload per vertical.
|
||||
// IMPORTANT: Only use "ALL:" rollup rows to avoid double-counting.
|
||||
// Each spreadsheet's Summary sheet contains both sub-team rows (ACCESS-OPS,
|
||||
// STEAM, etc.) AND a rollup row (ALL: NTS-AEO) per metric. The rollup row
|
||||
// already includes all sub-team totals, so summing all rows would double-count.
|
||||
const { rows: verticalSummary } = await pool.query(`
|
||||
SELECT vertical,
|
||||
SUM(total)::int AS total_devices,
|
||||
SUM(compliant)::int AS compliant,
|
||||
SUM(non_compliant)::int AS non_compliant
|
||||
FROM vcl_multi_vertical_summary
|
||||
WHERE upload_id = ANY($1)
|
||||
WHERE upload_id = ANY($1) AND team LIKE 'ALL:%'
|
||||
GROUP BY vertical
|
||||
ORDER BY vertical
|
||||
`, [latestUploadIds]);
|
||||
@@ -702,9 +709,10 @@ function createVCLMultiVerticalRouter(upload) {
|
||||
[uploadId, vertical]
|
||||
);
|
||||
|
||||
// Aggregate by category
|
||||
// Aggregate by category — only use "ALL:" rollup rows to avoid double-counting
|
||||
const categoryMap = {};
|
||||
for (const m of metrics) {
|
||||
if (!m.team || !m.team.startsWith('ALL:')) continue;
|
||||
const cat = m.category || 'Other';
|
||||
if (!categoryMap[cat]) categoryMap[cat] = { category: cat, non_compliant: 0, compliant: 0, total: 0 };
|
||||
categoryMap[cat].non_compliant += m.non_compliant;
|
||||
|
||||
Reference in New Issue
Block a user