fix(bi): add environment distribution breakdown to explain count discrepancies

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 <noreply@anthropic.com>
This commit is contained in:
TheFlow 2025-10-27 19:56:57 +13:00
parent 8c3ca56e2a
commit e99c85c4f2
2 changed files with 67 additions and 0 deletions

View file

@ -151,6 +151,19 @@
</div>
</div>
<!-- Environment Distribution (shows why totals may not match filtered views) -->
<div id="environment-distribution" class="bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6">
<h4 class="text-sm font-semibold text-gray-700 mb-3 flex items-center">
<svg class="w-4 h-4 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</svg>
Environment Distribution
</h4>
<div id="environment-stats" class="grid grid-cols-3 gap-3 text-sm">
<!-- Populated by JS -->
</div>
</div>
<!-- Business Intelligence Section -->
<div class="bg-gradient-to-r from-purple-50 to-blue-50 rounded-lg shadow-sm border-2 border-purple-200 p-6 mb-8">
<div class="flex items-center justify-between mb-4">

View file

@ -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 = `
<div class="text-center p-2 bg-blue-50 border border-blue-200 rounded">
<div class="font-semibold text-blue-700">Development</div>
<div class="text-2xl font-bold text-blue-900">${environmentStats.development}</div>
<div class="text-xs text-blue-600">${total > 0 ? ((environmentStats.development / total) * 100).toFixed(1) : 0}%</div>
</div>
<div class="text-center p-2 bg-green-50 border border-green-200 rounded">
<div class="font-semibold text-green-700">Production</div>
<div class="text-2xl font-bold text-green-900">${environmentStats.production}</div>
<div class="text-xs text-green-600">${total > 0 ? ((environmentStats.production / total) * 100).toFixed(1) : 0}%</div>
</div>
<div class="text-center p-2 bg-amber-50 border border-amber-200 rounded">
<div class="font-semibold text-amber-700">Unspecified</div>
<div class="text-2xl font-bold text-amber-900">${environmentStats.unspecified}</div>
<div class="text-xs text-amber-600">${total > 0 ? ((environmentStats.unspecified / total) * 100).toFixed(1) : 0}%</div>
</div>
`;
// Show warning if there are unspecified records
if (environmentStats.unspecified > 0) {
const warningHTML = `
<div class="col-span-3 mt-2 p-2 bg-amber-50 border border-amber-300 rounded text-xs text-amber-900">
<strong> Note:</strong> ${environmentStats.unspecified} record(s) have no environment field.
These are included in "All Environments" but excluded when filtering by Development or Production.
</div>
`;
statsEl.innerHTML += warningHTML;
}
}
// Render Business Intelligence