import type { Insertable, Transaction, Updateable } from "../generated/kysely-tailordb"; /** A journal entry owns its lines; all line persistence stays behind this repository. */ export function createJournalEntryRepository(db: Transaction) { return { async findById(id: string, opts?: { forUpdate?: boolean }) { let query = db.selectFrom("JournalEntry").selectAll().where("id", "=", id); if (opts?.forUpdate) query = query.forUpdate(); return (await query.executeTakeFirst()) ?? null; }, async findReversal(id: string) { return ( (await db .selectFrom("JournalEntry") .selectAll() .where("reversalOfId", "=", id) .executeTakeFirst()) ?? null ); }, async hasPeriodEntries(accountingPeriodId: string) { return !!(await db .selectFrom("JournalEntry") .selectAll() .where("accountingPeriodId", "=", accountingPeriodId) .executeTakeFirst()); }, async findLines(id: string) { return db.selectFrom("JournalLine").selectAll().where("journalEntryId", "=", id).execute(); }, async insert( header: Insertable<"JournalEntry">, lines: Omit, "journalEntryId">[], ) { const journalEntry = await db .insertInto("JournalEntry") .values(header) .returningAll() .executeTakeFirstOrThrow(); const journalLines = await db .insertInto("JournalLine") .values(lines.map((line) => ({ ...line, journalEntryId: journalEntry.id }))) .returningAll() .execute(); return { journalEntry, journalLines }; }, async update(id: string, data: Updateable<"JournalEntry">) { return db .updateTable("JournalEntry") .set(data) .where("id", "=", id) .returningAll() .executeTakeFirstOrThrow(); }, async editLines( id: string, changes: { updateLines: { lineId: string; patch: Updateable<"JournalLine"> }[]; removeLineIds: string[]; addLines: Omit, "journalEntryId">[]; }, ) { for (const { lineId, patch } of changes.updateLines) { if (Object.keys(patch).length === 0) continue; await db.updateTable("JournalLine").set(patch).where("id", "=", lineId).execute(); } if (changes.removeLineIds.length > 0) await db.deleteFrom("JournalLine").where("id", "in", changes.removeLineIds).execute(); if (changes.addLines.length > 0) await db .insertInto("JournalLine") .values(changes.addLines.map((line) => ({ ...line, journalEntryId: id }))) .execute(); }, }; } export type JournalEntryRepository = ReturnType;