import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import * as domain from "../domain/journalEntry"; import type { CreateJournalEntryInput, JournalEntryHeaderInput, JournalLineInput, } from "../domain/journalEntry"; import type { Transaction } from "../generated/kysely-tailordb"; export type { CreateJournalEntryInput, JournalEntryHeaderInput, JournalLineInput, } from "../domain/journalEntry"; import { CompanyNotFoundError } from "../lib/errors.generated"; import type { OrganizationQueries, CoaManagementQueries } from "../module"; import { createAccountingPeriodRepository, type AccountingPeriodRepository, } from "../repository/accountingPeriodRepository"; import { createJournalEntryRepository, type JournalEntryRepository, } from "../repository/journalEntryRepository"; export async function run( db: Transaction, input: Omit & { header: JournalEntryHeaderInput & HCF; lines: (JournalLineInput & LCF)[]; }, ctx: CommandContext, organizationQueries: Pick, coaManagementQueries: Pick, accountingPeriodRepositoryFactory: ( db: Transaction, ) => AccountingPeriodRepository = createAccountingPeriodRepository, journalEntryRepositoryFactory: ( db: Transaction, ) => JournalEntryRepository = createJournalEntryRepository, ) { const accountingPeriodRepository = accountingPeriodRepositoryFactory(db); const journalEntryRepository = journalEntryRepositoryFactory(db); const { companyId, accountingPeriodId } = input.header; const { company } = (await organizationQueries.getCompany(db, { id: companyId }, ctx)).value; if (!company) return err(new CompanyNotFoundError(companyId)); const period = await accountingPeriodRepository.findById(accountingPeriodId); const valid = domain.validateCreation(input.header, input.lines, true, period); if (!valid.ok) return valid; const accountIds = [...new Set(input.lines.map((line) => line.accountId))]; const accounts = ( await coaManagementQueries.listAccounts( db, { companyId, accountIds, limit: accountIds.length }, ctx, ) ).value.items; const validAccounts = domain.validateDraftLines(accountingPeriodId, input.lines, accounts); if (!validAccounts.ok) return validAccounts; const { journalEntry } = await journalEntryRepository.insert( domain.createDraft(input.header), input.lines, ); return ok({ journalEntry }); }