Sort the synthetic segment labels last, and drop their parentheses

Unordered, '(adjustment)' sorted *first* rather than last: '(' is 0x28 and
digits begin at 0x30, so it precedes '01 - Prior Year Sales'. The
parenthesised labels exist to mark a value as not a real segment, which is
exactly what an ordinal now does, so they get high ordinals and plain names
-- 98 - Unlabeled, 99 - Adjustments.

99 rather than max(seq) + 1 so the position does not shift every time a
segment is added or renumbered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Trowbridge 2026-09-17 13:47:49 -04:00
parent 5455d8089a
commit 7aaf017532

View File

@ -77,19 +77,27 @@ function sqlSafe(v) {
return String(v).replace(/'/g, "''") return String(v).replace(/'/g, "''")
} }
// pairs: [[rawValue, ordinal], ...]. Anything unlisted falls through to the raw // Anything unlisted falls through to the raw column.\n// pairs: [[rawValue, ordinal], ...] or [[rawValue, ordinal, displayAs], ...] where
// column, so it sorts after the ordered entries (digits before letters) rather // the third element renames the value as well as ordering it.
// than silently landing first. function buildOrderExpression(sourceCol, pairs, extra = []) {
function buildOrderExpression(sourceCol, pairs) { const cases = [...pairs, ...extra]
const cases = pairs
.filter(([label, ord]) => label && ord > 0 && isExprSafe(label)) .filter(([label, ord]) => label && ord > 0 && isExprSafe(label))
.sort((a, b) => a[1] - b[1]) .sort((a, b) => a[1] - b[1])
.map(([label, ord]) => .map(([label, ord, displayAs]) =>
`if ("${sourceCol}" == '${sqlSafe(label)}') { '${sqlSafe(orderedLabel(ord, label))}' }`) `if ("${sourceCol}" == '${sqlSafe(label)}') { '${sqlSafe(orderedLabel(ord, displayAs || label))}' }`)
if (cases.length === 0) return null if (cases.length === 0) return null
return `${cases.join('\nelse ')}\nelse { "${sourceCol}" }` return `${cases.join('\nelse ')}\nelse { "${sourceCol}" }`
} }
// The server's synthetic segment labels. Unordered they sort *first*, not last:
// '(' is 0x28 and digits begin at 0x30, so '(adjustment)' precedes '01 - ...'.
// They get high ordinals instead, and lose the parentheses those marked the
// value as not-a-real-segment, which the ordinal now does.
const SYNTHETIC_SEGMENTS = [
['(unlabeled load)', 98, 'Unlabeled'],
['(adjustment)', 99, 'Adjustments'],
]
// Build both expressions from the version's bucket_order and the log's seq values. // Build both expressions from the version's bucket_order and the log's seq values.
function buildOrderExpressions(bucketOrder, logMeta) { function buildOrderExpressions(bucketOrder, logMeta) {
const out = {} const out = {}
@ -105,7 +113,7 @@ function buildOrderExpressions(bucketOrder, logMeta) {
const segs = Object.values(logMeta || {}) const segs = Object.values(logMeta || {})
.filter(m => m.seq != null && ['baseline', 'reference'].includes(m.operation)) .filter(m => m.seq != null && ['baseline', 'reference'].includes(m.operation))
.map(m => [(m.tag || m.note || '').trim(), m.seq]) .map(m => [(m.tag || m.note || '').trim(), m.seq])
const segExpr = buildOrderExpression('pf_segment', segs) const segExpr = buildOrderExpression('pf_segment', segs, SYNTHETIC_SEGMENTS)
if (segExpr) out[ORDER_EXPR_NAMES.segment] = segExpr if (segExpr) out[ORDER_EXPR_NAMES.segment] = segExpr
return out return out