import { err, ok } from "@tailor-platform/erp-kit/core"; import { Decimal } from "decimal.js"; import type { Transaction } from "../../../generated/kysely-tailordb"; import { StandardCostNotFoundError } from "../../../lib/errors.generated"; import { pushNonZero, type CostingFact, type CostingRole } from "../journalEntry"; export async function priceStandardReceipt( db: Transaction, args: { itemId: string; quantity: Decimal; unitCost?: Decimal; counterpartRole: CostingRole; }, ) { const { itemId, quantity, unitCost, counterpartRole } = args; const standard = await db .selectFrom("StandardCost") .selectAll() .where("itemId", "=", itemId) .orderBy("version", "desc") .limit(1) .executeTakeFirst(); if (!standard) { return err(new StandardCostNotFoundError(itemId)); } const std = new Decimal(standard.unitCost); const actual = unitCost ?? std; const standardValue = std.mul(quantity); const actualValue = actual.mul(quantity); const variance = actualValue.minus(standardValue); const facts: CostingFact[] = []; pushNonZero(facts, { role: "INVENTORY", dcIndicator: "DR", amount: standardValue.toString(), }); pushNonZero(facts, { role: counterpartRole, dcIndicator: "CR", amount: actualValue.toString(), }); pushNonZero(facts, { role: "PPV", dcIndicator: variance.gt(0) ? "DR" : "CR", amount: variance.abs().toString(), }); return ok(facts); } export async function priceStandardIssue( db: Transaction, args: { itemId: string; quantity: Decimal; counterpartRole: CostingRole; }, ) { const { itemId, quantity, counterpartRole } = args; const standard = await db .selectFrom("StandardCost") .selectAll() .where("itemId", "=", itemId) .orderBy("version", "desc") .limit(1) .executeTakeFirst(); if (!standard) { return err(new StandardCostNotFoundError(itemId)); } const issueValue = new Decimal(standard.unitCost).mul(quantity); const facts: CostingFact[] = []; pushNonZero(facts, { role: counterpartRole, dcIndicator: "DR", amount: issueValue.toString(), }); pushNonZero(facts, { role: "INVENTORY", dcIndicator: "CR", amount: issueValue.toString(), }); return ok(facts); }