import fs from 'node:fs'; import { fileURLToPath } from 'node:url'; const docsDir = new URL('.', import.meta.url); const inputPath = new URL('./checked-sites-revision-audit-2026-06-04.json', docsDir); const outputPath = new URL('./checked-sites-revision-audit-2026-06-04.html', docsDir); const rows = JSON.parse(fs.readFileSync(inputPath, 'utf8')); const existingRows = rows.filter((row) => row.exists !== false); const activeRows = existingRows.filter((row) => row.hasActiveRevision === 'Yes'); const noActiveRows = existingRows.filter((row) => row.hasActiveRevision !== 'Yes'); const r00BilledRows = existingRows.filter((row) => row.r00Billed !== 'No'); const r00UnbilledRows = existingRows.filter((row) => row.r00Billed === 'No'); const activeStatusCounts = activeRows.reduce((acc, row) => { const key = row.activeStatus || 'unknown'; acc[key] = (acc[key] || 0) + 1; return acc; }, {}); const revisionDepthCounts = activeRows.reduce((acc, row) => { const key = row.activeRevision || '—'; acc[key] = (acc[key] || 0) + 1; return acc; }, {}); const maxStatusCount = Math.max(1, ...Object.values(activeStatusCounts)); const maxDepthCount = Math.max(1, ...Object.values(revisionDepthCounts)); const esc = (value) => String(value ?? '') .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); function badgeClassForStatus(status) { if (status === 'client_review') return 'review'; if (status === 'client_approved') return 'approved'; if (status === 'not_started') return 'todo'; if (status === 'in_progress') return 'progress'; return 'neutral'; } function barChart(entries, maxValue) { return entries .map(([label, count]) => { const pct = Math.max(4, Math.round((count / maxValue) * 100)); return `
`; }) .join(''); } function renderTableRows(items) { return items .map((row) => { const billedClass = row.r00Billed === 'No' ? 'warn' : 'ok'; const activeClass = badgeClassForStatus(row.activeStatus); return `This report treats your checkmark as “R00 was completed,” then separates that from billing and from any newer active revisions. It is designed to make client-billing comparison easier at a glance.
These are the ones where R00 may be done, but a newer version is still active or awaiting review/approval.
| Site # | DB Title | Internal # | R00 Done | R00 Billed | Active R# | Active Status | Completed Revisions | Billed Versions | Version Summary |
|---|
These are simpler to read: R00 completed, and no current revision chain is active right now.
| Site # | DB Title | Internal # | R00 Done | R00 Billed | Active R# | Active Status | Completed Revisions | Billed Versions | Version Summary |
|---|