import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import { Decimal } from "decimal.js"; import type { Selectable, Transaction } from "../generated/kysely-tailordb"; import { ApPurchaseOrderBillingSyncFailedError } from "../lib/errors.generated"; import type { PurchaseCommands } from "../module"; type AccountPayableDocument = Selectable<"AccountPayableDocument">; type AccountPayableDocumentLine = Selectable<"AccountPayableDocumentLine">; export async function syncPurchaseOrderBillingStatusFromAccountPayable( db: Transaction, input: { document: AccountPayableDocument; lines: AccountPayableDocumentLine[]; }, ctx: CommandContext, purchaseCommands: Pick, ) { const purchaseOrderLineIds = [ ...new Set( input.lines.map((line) => line.purchaseOrderLineId).filter((id): id is string => id !== null), ), ]; if (purchaseOrderLineIds.length === 0) { return ok(undefined); } const rows = await db .selectFrom("AccountPayableDocumentLine as line") .innerJoin("AccountPayableDocument as document", "document.id", "line.accountPayableDocumentId") .select([ "line.purchaseOrderLineId as purchaseOrderLineId", "line.quantity as quantity", "line.correctionType as correctionType", "document.documentType as documentType", ]) .where("line.purchaseOrderLineId", "in", purchaseOrderLineIds) .where("document.status", "in", ["REGISTERED", "POSTED"]) .execute(); const billedByLineId = new Map(); for (const row of rows) { if (row.purchaseOrderLineId === null || row.quantity === null) continue; if (row.correctionType === "PRICE" || row.correctionType === "AMOUNT") continue; const signedQuantity = row.documentType === "CREDIT_MEMO" ? new Decimal(row.quantity).neg() : new Decimal(row.quantity); billedByLineId.set( row.purchaseOrderLineId, (billedByLineId.get(row.purchaseOrderLineId) ?? new Decimal(0)).plus(signedQuantity), ); } const result = await purchaseCommands.recalculatePurchaseOrderBillingStatus( db, { lineBillings: purchaseOrderLineIds.map((purchaseOrderLineId) => ({ purchaseOrderLineId, billedQuantity: (billedByLineId.get(purchaseOrderLineId) ?? new Decimal(0)).toString(), })), }, ctx, ); if (!result.ok) { return err(new ApPurchaseOrderBillingSyncFailedError(input.document.id)); } return ok(undefined); }