import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core"; import type { ValuationPolicyCostingMethod } from "../generated/enums"; import type { Transaction } from "../generated/kysely-tailordb"; import { AccountNotFoundError, CompanyNotFoundError, DefaultValuationPolicyAlreadyExistsError, } from "../lib/errors.generated"; import type { CoaManagementQueries, OrganizationQueries } from "../module"; export interface CreateValuationPolicyInput { companyId: string; name: string; costingMethod: ValuationPolicyCostingMethod; isDefault?: boolean; inventoryAccountId: string; accrualAccountId: string; invoicePriceVarianceAccountId: string; cogsAccountId: string; ppvAccountId: string; adjustmentAccountId: string; standardCostAdjustmentAccountId: string; consumedPriceVarianceAccountId: string; } /** * Function: createValuationPolicy * * Creates a valuation policy defining the costing method and the owning * company's posting accounts. */ export async function run( db: Transaction, input: CreateValuationPolicyInput, ctx: CommandContext, organizationQueries: Pick, coaManagementQueries: Pick, ) { const { companyId, name, costingMethod, isDefault, inventoryAccountId, accrualAccountId, invoicePriceVarianceAccountId, cogsAccountId, ppvAccountId, adjustmentAccountId, standardCostAdjustmentAccountId, consumedPriceVarianceAccountId, } = input; const { company } = (await organizationQueries.getCompany(db, { id: companyId }, ctx)).value; if (!company) { return err(new CompanyNotFoundError(companyId)); } // Every posting account must exist in the company's chart of accounts. const accountIds = [ ...new Set([ inventoryAccountId, accrualAccountId, invoicePriceVarianceAccountId, cogsAccountId, ppvAccountId, adjustmentAccountId, standardCostAdjustmentAccountId, consumedPriceVarianceAccountId, ]), ]; const { items } = (await coaManagementQueries.listAccounts(db, { companyId, accountIds }, ctx)) .value; const foundAccountIds = new Set(items.map((account) => account.id)); for (const accountId of accountIds) { if (!foundAccountIds.has(accountId)) { return err(new AccountNotFoundError(accountId)); } } if (isDefault) { const existingDefault = await db .selectFrom("ValuationPolicy") .selectAll() .where("defaultCompanyId", "=", companyId) .executeTakeFirst(); if (existingDefault) { return err(new DefaultValuationPolicyAlreadyExistsError(existingDefault.id)); } } const policy = await db .insertInto("ValuationPolicy") .values({ companyId, name, costingMethod, // Unique defaultCompanyId backstops the check above under concurrency. defaultCompanyId: isDefault ? companyId : null, inventoryAccountId, accrualAccountId, invoicePriceVarianceAccountId, cogsAccountId, ppvAccountId, adjustmentAccountId, standardCostAdjustmentAccountId, consumedPriceVarianceAccountId, }) .returningAll() .executeTakeFirstOrThrow(); return ok({ valuationPolicy: policy }); }