import { ok, type CommandContext } from "@tailor-platform/erp-kit/core"; import { createDraft } from "../domain/inboundShipment"; import type { InboundShipmentLineSourceDocumentType, InboundShipmentLineStockType, } from "../generated/enums"; import type { Transaction } from "../generated/kysely-tailordb"; import type { InventoryQueries, ItemManagementQueries } from "../module"; import { createInboundShipmentRepository, type InboundShipmentRepository, } from "../repository/inboundShipmentRepository"; export interface InboundShipmentLineInput { itemId: string; storageLocationId: string; quantity: string; unitId: string; primaryQuantity: string; primaryUnitId: string; unitConversionRate: string; stockType?: InboundShipmentLineStockType; sourceDocumentType: InboundShipmentLineSourceDocumentType; sourceDocumentId: string; sourceLineId: string; } export interface InboundShipmentHeaderInput { effectiveDate: Date; } export interface CreateInboundShipmentInput { header: InboundShipmentHeaderInput; lines: InboundShipmentLineInput[]; } export async function run, LCF extends Record>( db: Transaction, input: { header: InboundShipmentHeaderInput & CF; lines: (InboundShipmentLineInput & LCF)[]; }, ctx: CommandContext, itemManagementQueries: Pick, inventoryQueries: Pick, repositoryFactory: ( db: Transaction, ) => InboundShipmentRepository = createInboundShipmentRepository, ) { const { effectiveDate, ...headerCustomFields } = input.header; // Whether a referenced record satisfies the rules is judged by the domain, // which treats a missing entry as a nonexistent reference. const itemById = new Map(); for (const itemId of new Set(input.lines.map((line) => line.itemId))) { const { item } = (await itemManagementQueries.getItem(db, { id: itemId }, ctx)).value; if (item) { itemById.set(itemId, item); } } const storageLocationById = new Map(); for (const locationId of new Set(input.lines.map((line) => line.storageLocationId))) { const { storageLocation } = ( await inventoryQueries.getStorageLocation(db, { id: locationId }, ctx) ).value; if (storageLocation) { storageLocationById.set(locationId, storageLocation); } } const shipment = createDraft( { effectiveDate, customFields: headerCustomFields, lines: input.lines.map((line) => { const { itemId, storageLocationId, quantity, unitId, primaryQuantity, primaryUnitId, unitConversionRate, stockType, sourceDocumentType, sourceDocumentId, sourceLineId, ...lineCustomFields } = line; return { itemId, storageLocationId, quantity, unitId, primaryQuantity, primaryUnitId, unitConversionRate, stockType, sourceDocumentType, sourceDocumentId, sourceLineId, customFields: lineCustomFields, }; }), }, { itemById, storageLocationById }, ); if (!shipment.ok) { return shipment; } await repositoryFactory(db).save(shipment.value); return ok({ inboundShipmentId: shipment.value.id }); }