import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import * as domain from "../domain/journalEntry"; import type { Transaction } from "../generated/kysely-tailordb"; import { JournalEntryNotFoundError, MinimumLinesNotMetError } from "../lib/errors.generated"; import type { CoaManagementQueries } from "../module"; import { createAccountingPeriodRepository, type AccountingPeriodRepository, } from "../repository/accountingPeriodRepository"; import { createJournalEntryRepository, type JournalEntryRepository, } from "../repository/journalEntryRepository"; export interface PostJournalEntryInput { id: string; } export async function run( db: Transaction, input: PostJournalEntryInput, ctx: CommandContext, coaManagementQueries: Pick, journalEntryRepositoryFactory: ( db: Transaction, ) => JournalEntryRepository = createJournalEntryRepository, accountingPeriodRepositoryFactory: ( db: Transaction, ) => AccountingPeriodRepository = createAccountingPeriodRepository, ) { const journalEntryRepository = journalEntryRepositoryFactory(db); const accountingPeriodRepository = accountingPeriodRepositoryFactory(db); const entry = await journalEntryRepository.findById(input.id, { forUpdate: true }); if (!entry) return err(new JournalEntryNotFoundError(input.id)); const validStatus = domain.validatePostStatus(entry); if (!validStatus.ok) return validStatus; const lines = await journalEntryRepository.findLines(entry.id); if (lines.length < 2) return err(new MinimumLinesNotMetError(entry.id)); const period = await accountingPeriodRepository.findById(entry.accountingPeriodId); const valid = domain.validatePosting(entry, lines, period); if (!valid.ok) return valid; const accountIds = [...new Set(lines.map((line) => line.accountId))]; const accounts = ( await coaManagementQueries.listAccounts( db, { companyId: entry.companyId, accountIds, limit: accountIds.length }, ctx, ) ).value.items; const changed = domain.post(entry, lines, { period, accounts }, new Date()); if (!changed.ok) return changed; const journalEntry = await journalEntryRepository.update(entry.id, changed.value); return ok({ journalEntry }); }