import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import { Decimal } from "decimal.js"; import type { InventorySupplyPlanSourceType } from "../generated/enums"; import type { Transaction } from "../generated/kysely-tailordb"; import { InvalidSupplyPlanQuantitiesError, ItemNotFoundError, SiteNotFoundError, SupplyPlanUnitMismatchError, } from "../lib/errors.generated"; import type { ItemManagementQueries, OrganizationQueries } from "../module"; export interface CreateInventorySupplyPlanLineInput { sourceLineId: string; itemId: string; siteId: string; expectedQuantity: string; unitId: string; expectedDate: Date; } export interface CreateInventorySupplyPlanInput { sourceType: InventorySupplyPlanSourceType; sourceId: string; supplyPlans: Array; } export async function run( db: Transaction, input: CreateInventorySupplyPlanInput, ctx: CommandContext, itemManagementQueries: Pick, organizationQueries: Pick, ) { if (input.supplyPlans.length === 0) { return ok({ supplyPlans: [] }); } const values = []; for (const supplyPlanInput of input.supplyPlans) { const { sourceLineId, itemId, siteId, expectedQuantity: inputExpectedQuantity, unitId, expectedDate, ...customFields } = supplyPlanInput; const expectedQuantity = new Decimal(inputExpectedQuantity); if (expectedQuantity.lt(0)) { return err(new InvalidSupplyPlanQuantitiesError(inputExpectedQuantity)); } const { item } = (await itemManagementQueries.getItem(db, { id: itemId }, ctx)).value; if (!item) { return err(new ItemNotFoundError(itemId)); } if (unitId !== item.unitId) { return err(new SupplyPlanUnitMismatchError(`${unitId} expected ${item.unitId}`)); } const { site } = (await organizationQueries.getSite(db, { id: siteId }, ctx)).value; if (!site) { return err(new SiteNotFoundError(siteId)); } values.push({ ...(customFields as Record), sourceType: input.sourceType, sourceId: input.sourceId, sourceLineId, itemId, siteId, expectedQuantity: inputExpectedQuantity, receivedQuantity: "0", status: "OPEN" as const, expectedDate, createdAt: new Date(), }); } const supplyPlans = await db .insertInto("InventorySupplyPlan") .values(values) .returningAll() .execute(); return ok({ supplyPlans }); }