fix: correct housekeeping module bugs after merge

- Restore migration order: remove spurious v30 birthday-reminders entry
  inserted before CardDAV (v30) and birthday-reminders (v31), which caused
  a duplicate v31 on fresh installs
- Restore birthdayReminderAt() offsetMin handling (regression from merge)
- Fix check-in INSERT: check_out was set to checkIn instead of NULL,
  making sessions invisible to loadOpenSession (IS NULL query)
- Implement check-out path in toggleSession() — only check-in was reachable
- Wrap GET /task-templates in try/catch per project convention
- Fix DELETE response envelopes: { ok: true } → { data: ... }
- Remove housekeeping worker exclusion from GET /auth/users
- Replace toISOString() with local-date helper to avoid UTC date shift
- Use user currency preference in money() instead of hardcoded BRL
- Replace hardcoded #7C3AED fallbacks in style attrs with CSS token
- Add German translations for documents folder and settings housekeeping keys
- Remove DESIGN.md and IMPLEMENTATION.md (AI planning artifacts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ulas Kalayci
2026-05-08 20:18:26 +02:00
parent 22ec13e559
commit 761408ae7c
8 changed files with 54 additions and 272 deletions
+9 -4
View File
@@ -430,7 +430,12 @@ router.get('/dashboard', (_req, res) => {
});
router.get('/task-templates', (_req, res) => {
res.json({ data: TASK_TEMPLATES });
try {
res.json({ data: TASK_TEMPLATES });
} catch (err) {
log.error('GET /task-templates error:', err);
res.status(500).json({ error: 'Internal server error.', code: 500 });
}
});
router.get('/worker', (_req, res) => {
@@ -656,7 +661,7 @@ router.post('/work-sessions/check-in', (req, res) => {
return db.get().prepare(`
INSERT INTO housekeeping_work_sessions (worker_id, check_in, check_out, daily_rate, extras, calendar_event_id, payment_task_id, created_by)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`).run(worker.id, checkIn, checkIn, vDailyRate.value, vExtras.value ?? 0, eventId, taskId, actorId);
`).run(worker.id, checkIn, null, vDailyRate.value, vExtras.value ?? 0, eventId, taskId, actorId);
})();
const row = db.get().prepare('SELECT * FROM housekeeping_work_sessions WHERE id = ?').get(result.lastInsertRowid);
res.status(201).json({ data: publicSession(row), summary: monthlySummary() });
@@ -755,7 +760,7 @@ router.delete('/visits/:id', (req, res) => {
deleteVisitLinks(db.get(), existing);
db.get().prepare('DELETE FROM housekeeping_work_sessions WHERE id = ?').run(existing.id);
})();
res.json({ ok: true, summary: monthlySummary() });
res.json({ data: { summary: monthlySummary() } });
} catch (err) {
log.error('DELETE /visits/:id error:', err);
res.status(500).json({ error: 'Internal server error.', code: 500 });
@@ -885,7 +890,7 @@ router.delete('/decay-tasks/:taskId', (req, res) => {
if (vId.error) return res.status(400).json({ error: vId.error, code: 400 });
const result = db.get().prepare('DELETE FROM housekeeping_decay_tasks WHERE id = ?').run(vId.value);
if (result.changes === 0) return res.status(404).json({ error: 'Task not found.', code: 404 });
res.json({ ok: true });
res.json({ data: null });
} catch (err) {
log.error('DELETE /decay-tasks/:taskId error:', err);
res.status(500).json({ error: 'Internal server error.', code: 500 });