Campaigns table: click sources stacked so the Clicks column stays narrow, card layout up to 900px; audit alert-day persisted, rounding-scale diffs ignored
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,7 @@ async function run() {
|
||||
const rows = await db.q('SELECT campaign_id, SUM(n) n FROM camp_hours GROUP BY campaign_id'); const h = {}; for (const r of rows) h[r.campaign_id] = Number(r.n);
|
||||
const issues = [];
|
||||
// only campaigns that started after the hourly log did
|
||||
for (const c of camps.filter(c => ['banner', 'text'].includes(c.type) && Number(c.created) >= logStartMs)) { const l = h[c.id] || 0; if (Math.abs(Number(c.imps) - l) > 2) issues.push('#' + c.id + ' ' + c.name.slice(0, 30) + ': ' + c.imps + ' views vs ' + l + ' in the hourly log'); }
|
||||
for (const c of camps.filter(c => ['banner', 'text'].includes(c.type) && Number(c.created) >= logStartMs)) { const l = h[c.id] || 0; if (Math.abs(Number(c.imps) - l) > Math.max(5, Math.round(0.02 * Math.max(Number(c.imps), l)))) issues.push('#' + c.id + ' ' + c.name.slice(0, 30) + ': ' + c.imps + ' views vs ' + l + ' in the hourly log'); }
|
||||
add('banner/text views vs hourly log', issues, camps.filter(c => ['banner', 'text'].includes(c.type) && Number(c.created) >= logStartMs).length + ' campaigns compared (started since the hourly log began ' + (logStart || '') + ')');
|
||||
}
|
||||
// 3. login: days charged vs days shown (a day may only be charged after the ad was shown)
|
||||
@@ -58,11 +58,14 @@ async function run() {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
let lastAlertDay = '';
|
||||
// the "once a day" memory lives on the volume: a redeploy restarts the process, and Marty got an alert after every deploy (2026-09-15)
|
||||
const STATE = () => path.join(R.dataDir, 'audit-state.json');
|
||||
function lastAlertDay() { try { return JSON.parse(fs.readFileSync(STATE(), 'utf8')).lastAlertDay || ''; } catch (e) { return ''; } }
|
||||
function setAlertDay(d) { try { fs.writeFileSync(STATE(), JSON.stringify({ lastAlertDay: d })); } catch (e) {} }
|
||||
async function dailyTick() {
|
||||
try {
|
||||
const r = await run(); const bad = r.checks.filter(c => !c.ok); const day = new Date().toISOString().slice(0, 10);
|
||||
if (bad.length && lastAlertDay !== day && R && R.notify) { lastAlertDay = day; R.notify('⚠️ InstantAdPay counter audit found ' + bad.length + ' issue' + (bad.length === 1 ? '' : 's') + ': ' + bad.map(c => c.name + ' (' + c.issues.length + ')').join('; ') + '. Admin > Reports > Counters audit.'); }
|
||||
if (bad.length && lastAlertDay() !== day && R && R.notify) { setAlertDay(day); R.notify('⚠️ InstantAdPay counter audit found ' + bad.length + ' issue' + (bad.length === 1 ? '' : 's') + ': ' + bad.map(c => c.name + ' (' + c.issues.length + ')').join('; ') + '. Admin > Reports > Counters audit.'); }
|
||||
return r;
|
||||
} catch (e) { console.error('audit', e.message); return null; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user