Make units column optional throughout source registration and SQL generation
- SQL generator no longer requires a units col; recode/clone/scale omit units expressions when none is configured in col_meta - Source registration validation drops units from required roles (value + date are the only hard requirements) - DELETE /api/sources/:id returns 409 when existing versions reference the source - Setup.jsx surfaces the 409 error via flash instead of silently failing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
101cb27604
commit
54c93c28dd
@ -21,7 +21,6 @@ function generateSQL(source, colMeta) {
|
||||
const dateCol = colMeta.find(c => c.role === 'date')?.cname;
|
||||
|
||||
if (!valueCol) throw new Error('No value column defined in col_meta');
|
||||
if (!unitsCol) throw new Error('No units column defined in col_meta');
|
||||
if (!dateCol) throw new Error('No date column defined in col_meta');
|
||||
if (dims.length === 0) throw new Error('No dimension columns defined in col_meta');
|
||||
|
||||
@ -171,14 +170,14 @@ ilog AS (
|
||||
)
|
||||
,neg AS (
|
||||
INSERT INTO {{fc_table}} (${insertCols})
|
||||
SELECT ${dimsJoined}, ${q(dateCol)}, ${effectiveValue ? `-${q(effectiveValue)}` : '0'}, ${effectiveUnits ? `-${q(effectiveUnits)}` : '0'},
|
||||
SELECT ${dimsJoined}, ${q(dateCol)}, ${effectiveValue ? `-${q(effectiveValue)}` : '0'}${effectiveUnits ? `, -${q(effectiveUnits)}` : ''},
|
||||
'recode', (SELECT id FROM ilog), '{{pf_user}}', now()
|
||||
FROM src
|
||||
RETURNING *
|
||||
)
|
||||
,ins AS (
|
||||
INSERT INTO {{fc_table}} (${insertCols})
|
||||
SELECT {{set_clause}}, ${q(dateCol)}, ${effectiveValue ? q(effectiveValue) : '0'}, ${effectiveUnits ? q(effectiveUnits) : '0'},
|
||||
SELECT {{set_clause}}, ${q(dateCol)}, ${effectiveValue ? q(effectiveValue) : '0'}${effectiveUnits ? `, ${q(effectiveUnits)}` : ''},
|
||||
'recode', (SELECT id FROM ilog), '{{pf_user}}', now()
|
||||
FROM src
|
||||
RETURNING *
|
||||
@ -199,8 +198,7 @@ ilog AS (
|
||||
SELECT
|
||||
{{set_clause}},
|
||||
${q(dateCol)},
|
||||
${effectiveValue ? `round(${q(effectiveValue)} * {{scale_factor}}, 2)` : '0'},
|
||||
${effectiveUnits ? `round(${q(effectiveUnits)} * {{scale_factor}}, 5)` : '0'},
|
||||
${effectiveValue ? `round(${q(effectiveValue)} * {{scale_factor}}, 2)` : '0'}${effectiveUnits ? `,\n round(${q(effectiveUnits)} * {{scale_factor}}, 5)` : ''},
|
||||
'clone', (SELECT id FROM ilog), '{{pf_user}}', now()
|
||||
FROM {{fc_table}}
|
||||
WHERE {{where_clause}}
|
||||
|
||||
@ -143,7 +143,7 @@ module.exports = function(pool) {
|
||||
// validate required roles
|
||||
const colMeta = colResult.rows;
|
||||
const roles = new Set(colMeta.map(c => c.role));
|
||||
const missing = ['value', 'units', 'date'].filter(r => !roles.has(r));
|
||||
const missing = ['value', 'date'].filter(r => !roles.has(r));
|
||||
if (missing.length > 0) {
|
||||
return res.status(400).json({
|
||||
error: `col_meta is missing required roles: ${missing.join(', ')}`
|
||||
@ -292,6 +292,9 @@ module.exports = function(pool) {
|
||||
res.json({ message: 'Source deregistered', source: result.rows[0] });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (err.code === '23001' || err.code === '23503') {
|
||||
return res.status(409).json({ error: 'Source has existing versions — delete them first.' });
|
||||
}
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
@ -140,7 +140,12 @@ export default function Setup({ refreshSources }) {
|
||||
async function deleteSource(id, e) {
|
||||
e.stopPropagation()
|
||||
if (!confirm('Deregister this source? Existing forecast tables are not affected.')) return
|
||||
await fetch(`/api/sources/${id}`, { method: 'DELETE' })
|
||||
const res = await fetch(`/api/sources/${id}`, { method: 'DELETE' })
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}))
|
||||
flash(data.error || 'Delete failed', 'err')
|
||||
return
|
||||
}
|
||||
if (selectedSource?.id === id) { setSelectedSource(null); setCols([]); setEditedCols([]) }
|
||||
loadSources()
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user