From 660a3ffa1c89502e9a4957c67f2dd4b87f717173 Mon Sep 17 00:00:00 2001 From: Ulas Date: Fri, 3 Apr 2026 18:28:31 +0200 Subject: [PATCH] fix(budget): fix category update failing with SQLite binding error The `date` import from validate.js shadowed the `date` field from req.body, so SQLite received a function reference instead of a string when updating a budget entry - causing a TypeError. Fix by aliasing the import to `validateDate` and adding `date` to the req.body destructuring. Closes #8 Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 5 +++++ server/routes/budget.js | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 967f988..766a41f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.6.0] - 2026-04-03 + +### Fixed +- Fix budget entry update failing with "Internal Error" when changing category - `date` validator import shadowed the `date` field from the request body, causing SQLite to receive a function reference instead of a string value (fixes #8) + ## [0.5.9] - 2026-04-03 ### Security diff --git a/server/routes/budget.js b/server/routes/budget.js index 98722f1..e568d0d 100644 --- a/server/routes/budget.js +++ b/server/routes/budget.js @@ -9,7 +9,7 @@ const express = require('express'); const router = express.Router(); const db = require('../db'); -const { str, oneOf, date, num, rrule, collectErrors, MAX_TITLE, MONTH_RE } = require('../middleware/validate'); +const { str, oneOf, date: validateDate, num, rrule, collectErrors, MAX_TITLE, MONTH_RE } = require('../middleware/validate'); // -------------------------------------------------------- // Wiederkehrende Einträge: fehlende Instanzen für einen Monat erzeugen @@ -237,7 +237,7 @@ router.post('/', (req, res) => { const vTitle = str(req.body.title, 'Titel', { max: MAX_TITLE }); const vAmount = num(req.body.amount, 'Betrag', { required: true }); const vCat = oneOf(req.body.category || 'Sonstiges', VALID_CATEGORIES, 'Kategorie'); - const vDate = date(req.body.date, 'Datum', true); + const vDate = validateDate(req.body.date, 'Datum', true); const vRrule = rrule(req.body.recurrence_rule, 'Wiederholung'); const errors = collectErrors([vTitle, vAmount, vCat, vDate, vRrule]); if (errors.length) return res.status(400).json({ error: errors.join(' '), code: 400 }); @@ -280,11 +280,11 @@ router.put('/:id', (req, res) => { if (req.body.title !== undefined) checks.push(str(req.body.title, 'Titel', { max: MAX_TITLE, required: false })); if (req.body.amount !== undefined) checks.push(num(req.body.amount, 'Betrag')); if (req.body.category !== undefined) checks.push(oneOf(req.body.category, VALID_CATEGORIES, 'Kategorie')); - if (req.body.date !== undefined) checks.push(date(req.body.date, 'Datum')); + if (req.body.date !== undefined) checks.push(validateDate(req.body.date, 'Datum')); if (req.body.recurrence_rule !== undefined) checks.push(rrule(req.body.recurrence_rule, 'Wiederholung')); const errors = collectErrors(checks); if (errors.length) return res.status(400).json({ error: errors.join(' '), code: 400 }); - const { title, amount, category, is_recurring, recurrence_rule } = req.body; + const { title, amount, category, date, is_recurring, recurrence_rule } = req.body; db.get().prepare(` UPDATE budget_entries