import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import * as domain from "../domain/fiscalYear"; import type { UpdateFiscalYearInput } from "../domain/fiscalYear"; import type { Transaction } from "../generated/kysely-tailordb"; export type { UpdateFiscalYearInput } from "../domain/fiscalYear"; import { FiscalYearNotFoundError, OverlappingFiscalYearError } from "../lib/errors.generated"; import { createAccountingPeriodRepository, type AccountingPeriodRepository, } from "../repository/accountingPeriodRepository"; import { createFiscalYearRepository, type FiscalYearRepository, } from "../repository/fiscalYearRepository"; export async function run>( db: Transaction, input: UpdateFiscalYearInput & Partial, _ctx: CommandContext, fiscalYearRepositoryFactory: ( db: Transaction, ) => FiscalYearRepository = createFiscalYearRepository, accountingPeriodRepositoryFactory: ( db: Transaction, ) => AccountingPeriodRepository = createAccountingPeriodRepository, ) { const fiscalYearRepository = fiscalYearRepositoryFactory(db); const accountingPeriodRepository = accountingPeriodRepositoryFactory(db); const existing = await fiscalYearRepository.findById(input.id, { forUpdate: true }); if (!existing) return err(new FiscalYearNotFoundError(input.id)); const validName = domain.validateNameChange(input.id, input.yearName); if (!validName.ok) return validName; const datesRequested = input.startDate !== undefined || input.endDate !== undefined; const periodsExist = datesRequested && (await accountingPeriodRepository.hasFiscalYearPeriods(input.id)); const prepared = domain.update(existing, input, { periodsExist }); if (!prepared.ok) return prepared; if (datesRequested) { const overlapping = await fiscalYearRepository.findOverlapping( existing.companyId, input.startDate ?? existing.startDate, input.endDate ?? existing.endDate, input.id, ); if (overlapping) return err(new OverlappingFiscalYearError(input.id)); } const fiscalYear = Object.keys(prepared.value).length === 0 ? existing : await fiscalYearRepository.update(input.id, prepared.value); return ok({ fiscalYear }); }