From e99c85c4f2337ff08501cfd0b46a62aab5f0d918 Mon Sep 17 00:00:00 2001 From: TheFlow Date: Mon, 27 Oct 2025 19:56:57 +1300 Subject: [PATCH] fix(bi): add environment distribution breakdown to explain count discrepancies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Users noticed environment counts don't add up to total - Total (All Environments): 868 - Development: 400 - Production: 300 - 400 + 300 = 700 ≠ 868 Root cause: Some audit logs have no environment field (null/undefined) - These records ARE counted in "All Environments" - These records are NOT counted when filtering by "Development" or "Production" Solution: - Added "Environment Distribution" section showing breakdown - Displays: Development, Production, and Unspecified counts - Shows warning when unspecified records exist - Makes it clear why filtered totals may not match grand total Technical details: - Frontend filtering in audit-analytics.js - Backend query uses: query.environment = environment (exact match only) - Missing environment fields excluded from filtered results 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- public/admin/audit-analytics.html | 13 +++++++ public/js/admin/audit-analytics.js | 54 ++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/public/admin/audit-analytics.html b/public/admin/audit-analytics.html index 6cfd6a4b..fa3bc306 100644 --- a/public/admin/audit-analytics.html +++ b/public/admin/audit-analytics.html @@ -151,6 +151,19 @@ + +
+

+ + + + Environment Distribution +

+
+ +
+
+
diff --git a/public/js/admin/audit-analytics.js b/public/js/admin/audit-analytics.js index 5892a1ca..b725f0e6 100644 --- a/public/js/admin/audit-analytics.js +++ b/public/js/admin/audit-analytics.js @@ -138,6 +138,60 @@ function updateSummaryCards() { document.getElementById('violations-count').textContent = violationsCount; document.getElementById('services-count').textContent = servicesSet.size || 0; + + // Environment distribution breakdown + updateEnvironmentDistribution(); +} + +// Update environment distribution display +function updateEnvironmentDistribution() { + const environmentStats = { + development: 0, + production: 0, + unspecified: 0 + }; + + auditData.forEach(d => { + if (d.environment === 'development') { + environmentStats.development++; + } else if (d.environment === 'production') { + environmentStats.production++; + } else { + environmentStats.unspecified++; + } + }); + + const total = auditData.length; + const statsEl = document.getElementById('environment-stats'); + + statsEl.innerHTML = ` +
+
Development
+
${environmentStats.development}
+
${total > 0 ? ((environmentStats.development / total) * 100).toFixed(1) : 0}%
+
+
+
Production
+
${environmentStats.production}
+
${total > 0 ? ((environmentStats.production / total) * 100).toFixed(1) : 0}%
+
+
+
Unspecified
+
${environmentStats.unspecified}
+
${total > 0 ? ((environmentStats.unspecified / total) * 100).toFixed(1) : 0}%
+
+ `; + + // Show warning if there are unspecified records + if (environmentStats.unspecified > 0) { + const warningHTML = ` +
+ ⚠️ Note: ${environmentStats.unspecified} record(s) have no environment field. + These are included in "All Environments" but excluded when filtering by Development or Production. +
+ `; + statsEl.innerHTML += warningHTML; + } } // Render Business Intelligence