Close the write-only surface left behind by the ordinals
bucket_order and log.seq were still settable -- PUT /versions/:id took the first, PATCH /log/:logid the second -- with nothing left to read either. A field that only ever gets written is worse than a missing one: the call succeeds, so the caller has no way to find out it did nothing. The columns themselves stay, marked vestigial where they are declared. Dropping a column is not worth a migration to reclaim two that cost nothing. pf.log.bucket is untouched and stays exactly as it was -- what a row counts toward, read first by BUCKET_EXPR. It is the bucket *order* that no longer needs storing, the text having become the order. Also removes a comment head in Forecast.jsx that survived its function and had glued itself onto fitColumns. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3299bfe10b
commit
98322a6080
@ -131,11 +131,11 @@ module.exports = function(pool) {
|
||||
// a closed version, where relabelling history is still legitimate.
|
||||
router.patch('/log/:logid', async (req, res) => {
|
||||
const logId = parseInt(req.params.logid);
|
||||
const { note, tag, bucket, seq, label } = req.body;
|
||||
if (note === undefined && tag === undefined && bucket === undefined
|
||||
&& seq === undefined && label === undefined) {
|
||||
const { note, tag, bucket, label } = req.body;
|
||||
if (note === undefined && tag === undefined
|
||||
&& bucket === undefined && label === undefined) {
|
||||
return res.status(400).json({
|
||||
error: 'Nothing to update — send note, tag, bucket, label and/or seq'
|
||||
error: 'Nothing to update — send note, tag, bucket and/or label'
|
||||
});
|
||||
}
|
||||
try {
|
||||
@ -146,16 +146,13 @@ module.exports = function(pool) {
|
||||
note = CASE WHEN $2::bool THEN $3::text ELSE note END,
|
||||
tag = CASE WHEN $4::bool THEN $5::text ELSE tag END,
|
||||
bucket = CASE WHEN $6::bool THEN $7::text ELSE bucket END,
|
||||
seq = CASE WHEN $8::bool THEN $9::int ELSE seq END,
|
||||
label = CASE WHEN $10::bool THEN $11::text ELSE label END
|
||||
label = CASE WHEN $8::bool THEN $9::text ELSE label END
|
||||
WHERE id = $1 RETURNING *`,
|
||||
[
|
||||
logId,
|
||||
note !== undefined, note === undefined ? null : (String(note).trim() || null),
|
||||
tag !== undefined, tag === undefined ? null : (String(tag).trim() || null),
|
||||
bucket !== undefined, bucket === undefined ? null : (String(bucket).trim() || null),
|
||||
seq !== undefined, (seq === undefined || seq === null || seq === '')
|
||||
? null : parseInt(seq),
|
||||
label !== undefined, label === undefined ? null : (String(label).trim() || null),
|
||||
]
|
||||
);
|
||||
|
||||
@ -308,27 +308,25 @@ ${colDefs},
|
||||
});
|
||||
|
||||
// update version name, description, or exclude_iters
|
||||
//
|
||||
// bucket_order is deliberately not settable: the bucket column order is the
|
||||
// text in pf.log.bucket now, so a stored order would be a second answer to
|
||||
// the same question, and a silent one -- nothing reads it.
|
||||
router.put('/versions/:id', async (req, res) => {
|
||||
const { name, description, exclude_iters, bucket_order } = req.body;
|
||||
const { name, description, exclude_iters } = req.body;
|
||||
try {
|
||||
// bucket_order is a flag-and-value pair rather than COALESCE: an empty
|
||||
// array is a meaningful value (no ordering), and COALESCE could not tell
|
||||
// it from "not mentioned".
|
||||
const result = await pool.query(`
|
||||
UPDATE pf.version SET
|
||||
name = COALESCE($2, name),
|
||||
description = COALESCE($3, description),
|
||||
exclude_iters = COALESCE($4, exclude_iters),
|
||||
bucket_order = CASE WHEN $5::bool THEN $6::jsonb ELSE bucket_order END
|
||||
exclude_iters = COALESCE($4, exclude_iters)
|
||||
WHERE id = $1
|
||||
RETURNING *
|
||||
`, [
|
||||
req.params.id,
|
||||
name || null,
|
||||
description || null,
|
||||
exclude_iters ? JSON.stringify(exclude_iters) : null,
|
||||
bucket_order !== undefined,
|
||||
bucket_order === undefined ? null : JSON.stringify(bucket_order || [])
|
||||
exclude_iters ? JSON.stringify(exclude_iters) : null
|
||||
]);
|
||||
if (result.rows.length === 0) {
|
||||
return res.status(404).json({ error: 'Version not found' });
|
||||
|
||||
@ -83,15 +83,6 @@ WHERE TRUE
|
||||
|
||||
-- Display order for the pivot's segment and bucket columns.
|
||||
--
|
||||
-- Perspective orders column groups by the value string, and SortDir's col asc /
|
||||
-- col desc only reverses that -- so no sort setting can produce
|
||||
-- Prior Year -> Plan -> Actual -> Forecast, which is alphabetical in neither
|
||||
-- direction. The order has to be carried in the value itself, as a "01 · " style
|
||||
-- prefix applied when the rows are served.
|
||||
--
|
||||
-- bucket_order lives on the version rather than the source because the Baseline
|
||||
-- page, where it is maintained, is version-scoped. log.seq orders the segments
|
||||
-- within that.
|
||||
-- The segment's display name in the pivot, falling back to tag then note.
|
||||
--
|
||||
-- Separate from both because those have jobs already -- tag groups adjustments
|
||||
@ -101,6 +92,11 @@ WHERE TRUE
|
||||
-- note would put it in every note.
|
||||
ALTER TABLE pf.log ADD COLUMN IF NOT EXISTS label text;
|
||||
|
||||
-- Vestigial, both of them. They held the ordinal when the "01 - " prefix was
|
||||
-- computed for the pivot rather than typed into label and bucket: bucket_order
|
||||
-- sequenced the bucket columns, log.seq the segments within them. Nothing reads
|
||||
-- either now, and nothing writes them -- kept only because dropping a column is
|
||||
-- not worth a migration to reclaim two that cost nothing.
|
||||
ALTER TABLE pf.version ADD COLUMN IF NOT EXISTS bucket_order jsonb;
|
||||
ALTER TABLE pf.log ADD COLUMN IF NOT EXISTS seq integer;
|
||||
|
||||
|
||||
@ -841,10 +841,6 @@ export default function Forecast({ sources = [], sourceId, versions = [], versio
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the ordering expressions in step with the version's bucket_order and the
|
||||
// log's seq values. Merged into the live config rather than replacing
|
||||
// expressions, so anything the user defined themselves survives.
|
||||
//
|
||||
// Size every column to its contents.
|
||||
//
|
||||
// Values fit on their own: draw() calls regular_table.resetAutoSize(), which
|
||||
|
||||
Loading…
Reference in New Issue
Block a user