import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import * as domain from "../domain/journalEntry"; import type { UpdateJournalEntryInput, JournalEntryHeaderPatch, JournalLineInput, JournalLineEdit, JournalLinePatch, } from "../domain/journalEntry"; import type { Transaction } from "../generated/kysely-tailordb"; export type { UpdateJournalEntryInput, JournalEntryHeaderPatch, JournalLineInput, JournalLineEdit, JournalLinePatch, } from "../domain/journalEntry"; import { JournalEntryNotFoundError } from "../lib/errors.generated"; import type { CoaManagementQueries } from "../module"; import { createJournalEntryRepository, type JournalEntryRepository, } from "../repository/journalEntryRepository"; export async function run( db: Transaction, input: Omit & { headerPatch?: JournalEntryHeaderPatch & Partial; addLines?: (JournalLineInput & LCF)[]; updateLines?: (Omit & { patch: JournalLinePatch & Partial; })[]; }, ctx: CommandContext, coaManagementQueries: Pick, journalEntryRepositoryFactory: ( db: Transaction, ) => JournalEntryRepository = createJournalEntryRepository, ) { const journalEntryRepository = journalEntryRepositoryFactory(db); const { id, headerPatch, addLines = [], updateLines = [], removeLineIds = [] } = input; const existing = await journalEntryRepository.findById(id, { forUpdate: true }); if (!existing) return err(new JournalEntryNotFoundError(id)); const valid = domain.validateDraftChanges(existing, input); if (!valid.ok) return valid; const currentLines = await journalEntryRepository.findLines(id); const prepared = domain.prepareLines(id, currentLines, input); if (!prepared.ok) return prepared; const accountIds = [...new Set(prepared.value.map((line) => line.accountId))]; const accounts = ( await coaManagementQueries.listAccounts( db, { companyId: existing.companyId, accountIds, limit: accountIds.length }, ctx, ) ).value.items; const validAccounts = domain.validateDraftLines(id, prepared.value, accounts); if (!validAccounts.ok) return validAccounts; const header = domain.headerChanges(headerPatch); const journalEntry = Object.keys(header).length === 0 ? existing : await journalEntryRepository.update(id, header); await journalEntryRepository.editLines(id, { addLines, updateLines, removeLineIds }); return ok({ journalEntry }); }