feat: schedule queries

This commit is contained in:
2026-05-20 17:43:21 +02:00
parent 2218599106
commit 9a4e9c3e1e
2 changed files with 98 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
import { getDb, resetDb } from '../../db';
import {
insertScheduleEntry, getScheduleByDate, updateScheduleStatus,
getUpcomingSchedule, getPendingDates,
} from '../../db/schedule';
beforeEach(() => { resetDb(); });
describe('schedule', () => {
it('inserts and retrieves a schedule entry', () => {
const db = getDb();
insertScheduleEntry(db, '2026-05-22', 60, 'Continuing current level');
const e = getScheduleByDate(db, '2026-05-22');
expect(e).not.toBeNull();
expect(e!.planned_min).toBe(60);
expect(e!.status).toBe('pending');
});
it('updates status to completed', () => {
const db = getDb();
insertScheduleEntry(db, '2026-05-22', 60, null);
updateScheduleStatus(db, '2026-05-22', 'completed', null);
expect(getScheduleByDate(db, '2026-05-22')!.status).toBe('completed');
});
it('updates status to skipped with reason', () => {
const db = getDb();
insertScheduleEntry(db, '2026-05-22', 60, null);
updateScheduleStatus(db, '2026-05-22', 'skipped', 'work trip');
const e = getScheduleByDate(db, '2026-05-22')!;
expect(e.status).toBe('skipped');
expect(e.skip_reason).toBe('work trip');
});
it('returns upcoming entries from today onwards ordered by date', () => {
const db = getDb();
insertScheduleEntry(db, '2026-05-21', 60, null);
insertScheduleEntry(db, '2026-05-23', 75, null);
const rows = getUpcomingSchedule(db, '2026-05-21');
expect(rows).toHaveLength(2);
expect(rows[0]!.date).toBe('2026-05-21');
});
it('returns only pending dates', () => {
const db = getDb();
insertScheduleEntry(db, '2026-05-21', 60, null);
insertScheduleEntry(db, '2026-05-22', 60, null);
updateScheduleStatus(db, '2026-05-21', 'completed', null);
expect(getPendingDates(db)).toEqual(['2026-05-22']);
});
});
+47
View File
@@ -0,0 +1,47 @@
import type { Database } from 'better-sqlite3';
export type ScheduleStatus = 'pending' | 'completed' | 'skipped';
export interface ScheduleEntry {
id: number;
date: string;
planned_min: number;
status: ScheduleStatus;
skip_reason: string | null;
ai_rationale: string | null;
created_at: string;
}
export function insertScheduleEntry(
db: Database, date: string, planned_min: number, ai_rationale: string | null
): ScheduleEntry {
db.prepare(
'INSERT OR IGNORE INTO schedule (date, planned_min, ai_rationale) VALUES (?, ?, ?)'
).run(date, planned_min, ai_rationale);
return getScheduleByDate(db, date)!;
}
export function getScheduleByDate(db: Database, date: string): ScheduleEntry | null {
return (db.prepare('SELECT * FROM schedule WHERE date = ?').get(date) as ScheduleEntry | undefined) ?? null;
}
export function updateScheduleStatus(
db: Database, date: string, status: ScheduleStatus, skip_reason: string | null
): void {
db.prepare(
'UPDATE schedule SET status = ?, skip_reason = ? WHERE date = ?'
).run(status, skip_reason, date);
}
export function getUpcomingSchedule(db: Database, fromDate: string): ScheduleEntry[] {
return db.prepare(
'SELECT * FROM schedule WHERE date >= ? ORDER BY date ASC'
).all(fromDate) as ScheduleEntry[];
}
export function getPendingDates(db: Database): string[] {
const rows = db.prepare(
"SELECT date FROM schedule WHERE status = 'pending' ORDER BY date ASC"
).all() as Array<{ date: string }>;
return rows.map(r => r.date);
}