Initial commit — utilities app (meter readings, tariffs, cost tracking)
Fastify + pg backend, React/TS/Vite frontend. Categories (electric, gas, oil, water), meters with sub-metering rollup, tariffs with time-of-use rate windows, standing charges, Climate Change Levy and VAT, manual reading entry, consumption/cost reports, period cost estimates, and an API-key-gated /api/internal/* surface for the reports app's Directors Report. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
commit
4fc5230d79
44 changed files with 10249 additions and 0 deletions
27
backend/src/routes/settings.js
Normal file
27
backend/src/routes/settings.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { requireAuth, requireCap } from '../auth.js'
|
||||
import { pool } from '../db.js'
|
||||
|
||||
export async function settingsRoutes(app) {
|
||||
app.addHook('preHandler', requireAuth)
|
||||
|
||||
// GET /api/config — all config keys as a flat object (readable by anyone in
|
||||
// the app since the estimates page needs the global default too)
|
||||
app.get('/api/config', async () => {
|
||||
const { rows } = await pool.query('SELECT key, value FROM config ORDER BY key')
|
||||
return Object.fromEntries(rows.map(r => [r.key, r.value]))
|
||||
})
|
||||
|
||||
// PUT /api/config/:key — update a single config key
|
||||
app.put('/api/config/:key', { preHandler: requireCap('settings') }, async (req, reply) => {
|
||||
const { key } = req.params
|
||||
const { value } = req.body || {}
|
||||
if (value === undefined) return reply.status(400).send({ error: 'value required' })
|
||||
|
||||
await pool.query(
|
||||
`INSERT INTO config (key, value, updated_at) VALUES ($1, $2, NOW())
|
||||
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()`,
|
||||
[key, JSON.stringify(value)]
|
||||
)
|
||||
return { ok: true }
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue