From 2689e95b2c258ccc366da1b3c8364c65d9b93643 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 17 Sep 2026 01:03:34 -0400 Subject: [PATCH] Count adjustments as Forecast rather than their own banner pf_bucket mirrored pf_segment for scale/recode/clone rows, so adjustments showed as '(adjustment)' -- a banner of their own, sitting outside the forecast they are adjustments to. Grouping by pf_bucket therefore split the forecast in two. An adjustment is always part of the forecast: exclude_iters keeps operations off the reference segments, so there is no adjustment that is not. It falls back to 'Forecast' now, and still yields to an explicit bucket on its own log entry. pf_segment keeps '(adjustment)', which is right there -- it answers which segment a row came from, and an adjustment came from none. Co-Authored-By: Claude Opus 5 (1M context) --- lib/sql_generator.js | 2 +- routes/operations.js | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/sql_generator.js b/lib/sql_generator.js index 4a9873d..902fc04 100644 --- a/lib/sql_generator.js +++ b/lib/sql_generator.js @@ -154,7 +154,7 @@ SELECT ,COALESCE(NULLIF(l.bucket, ''), CASE WHEN l.operation IN ('baseline','reference') THEN COALESCE(NULLIF(l.tag, ''), NULLIF(l.note, ''), '(unlabeled load)') - ELSE '(adjustment)' END) AS pf_bucket + ELSE 'Forecast' END) AS pf_bucket ,CASE WHEN l.operation IN ('baseline','reference') THEN NULL ELSE COALESCE(NULLIF(l.tag, ''), NULLIF(l.note, '')) END AS pf_note diff --git a/routes/operations.js b/routes/operations.js index 3050444..7a2fe7f 100644 --- a/routes/operations.js +++ b/routes/operations.js @@ -319,12 +319,15 @@ module.exports = function(pool) { ,CASE WHEN l.operation IN ('baseline','reference') THEN COALESCE(NULLIF(l.tag, ''), NULLIF(l.note, ''), '(unlabeled load)') ELSE '(adjustment)' END AS pf_segment - -- what the segment counts towards, falling back to the segment - -- itself so an unlabelled one still reads as something + -- What the row counts towards. A load falls back to its own + -- name until it is labelled; an adjustment falls back to + -- 'Forecast', because that is what an adjustment is -- exclude_iters + -- keeps operations off the reference segments, so there is no + -- adjustment that is not part of the forecast. ,COALESCE(NULLIF(l.bucket, ''), CASE WHEN l.operation IN ('baseline','reference') THEN COALESCE(NULLIF(l.tag, ''), NULLIF(l.note, ''), '(unlabeled load)') - ELSE '(adjustment)' END) AS pf_bucket + ELSE 'Forecast' END) AS pf_bucket ,CASE WHEN l.operation IN ('baseline','reference') THEN NULL ELSE COALESCE(NULLIF(l.tag, ''), NULLIF(l.note, '')) END AS pf_note @@ -643,7 +646,7 @@ module.exports = function(pool) { await client.query('COMMIT'); committed = true; const opLabel = (req.body.tag || '').trim() || note || null; - const rows = allRows.map(r => ({ ...r, pf_segment: '(adjustment)', pf_bucket: '(adjustment)', pf_note: opLabel, pf_op: 'scale' })); + const rows = allRows.map(r => ({ ...r, pf_segment: '(adjustment)', pf_bucket: 'Forecast', pf_note: opLabel, pf_op: 'scale' })); res.json({ rows, rows_affected: rows.length, @@ -703,7 +706,7 @@ module.exports = function(pool) { await client.query('COMMIT'); committed = true; const opLabel = (req.body.tag || '').trim() || note || null; - const rows = allRows.map(r => ({ ...r, pf_segment: '(adjustment)', pf_bucket: '(adjustment)', pf_note: opLabel, pf_op: 'recode' })); + const rows = allRows.map(r => ({ ...r, pf_segment: '(adjustment)', pf_bucket: 'Forecast', pf_note: opLabel, pf_op: 'recode' })); res.json({ rows, rows_affected: rows.length, slices_applied: units.length }); } finally { if (!committed) try { await client.query('ROLLBACK'); } catch {} @@ -760,7 +763,7 @@ module.exports = function(pool) { await client.query('COMMIT'); committed = true; const opLabel = (req.body.tag || '').trim() || note || null; - const rows = allRows.map(r => ({ ...r, pf_segment: '(adjustment)', pf_bucket: '(adjustment)', pf_note: opLabel, pf_op: 'clone' })); + const rows = allRows.map(r => ({ ...r, pf_segment: '(adjustment)', pf_bucket: 'Forecast', pf_note: opLabel, pf_op: 'clone' })); res.json({ rows, rows_affected: rows.length, slices_applied: units.length }); } finally { if (!committed) try { await client.query('ROLLBACK'); } catch {}