import { type CommonReservedFields, type NoReservedFields, defaultGqlPermission, defaultPermission, } from "@tailor-platform/erp-kit/core"; import { db, type TailorAnyDBField, type TailorAnyDBType } from "@tailor-platform/sdk"; import { inboundShipment } from "./inboundShipment"; // Line-level source document types for inbound shipments. export const INBOUND_SHIPMENT_LINE_SOURCE_DOCUMENT_TYPES = ["PURCHASE_ORDER"] as const; // Must match inventory's STOCK_TYPES; duplicated locally to avoid a cross-module value import. export const STOCK_TYPES = ["AVAILABLE", "BLOCKED", "IN_TRANSIT"] as const; const builtins = (params: { itemType?: TailorAnyDBType; unitType?: TailorAnyDBType; storageLocationType?: TailorAnyDBType; }) => { const itemId = db.uuid().description("Foreign key to Item"); const unitId = db.uuid().description("Business/input Unit for quantity"); const primaryUnitId = db .uuid() .description("Snapshot of the item's primary Unit at shipment line creation time"); const storageLocationId = db.uuid().description("Storage location affected by this line"); return { inboundShipmentId: db .uuid() .relation({ type: "n-1", toward: { type: inboundShipment, as: "inboundShipment" }, backward: "lines", }) .description("Foreign key to InboundShipment header"), itemId: params.itemType ? itemId.relation({ type: "n-1", toward: { type: params.itemType, as: "item" }, backward: "inboundShipmentLines", }) : itemId, quantity: db.decimal().description("Business/input quantity in unitId"), unitId: params.unitType ? unitId.relation({ type: "n-1", toward: { type: params.unitType, as: "unit" }, backward: "inboundShipmentLines", }) : unitId, primaryQuantity: db .decimal() .description("Quantity converted to the item's primary unit at line creation time"), primaryUnitId: params.unitType ? primaryUnitId.relation({ type: "n-1", toward: { type: params.unitType, as: "primaryUnit" }, backward: "primaryInboundShipmentLines", }) : primaryUnitId, unitConversionRate: db .decimal() .description("Multiplier used to convert quantity into primaryQuantity"), unitCost: db .decimal({ optional: true }) .description("Primary-unit cost derived from the purchase-order line price at posting"), storageLocationId: params.storageLocationType ? storageLocationId.relation({ type: "n-1", toward: { type: params.storageLocationType, as: "storageLocation" }, backward: "inboundShipmentLines", }) : storageLocationId, stockType: db .enum([...STOCK_TYPES] as [string, ...string[]]) .description("Stock type affected by this line"), sourceDocumentType: db .enum(INBOUND_SHIPMENT_LINE_SOURCE_DOCUMENT_TYPES) .description("Source document type. Generic reference, not a typed foreign key."), sourceDocumentId: db .uuid() .description("Source document ID. Generic reference, not a typed foreign key."), sourceLineId: db .uuid() .description("Source document line ID. Generic reference, not a typed foreign key."), }; }; type ReservedFields = keyof ReturnType | CommonReservedFields; export interface CreateInboundShipmentLineTypeParams> { fields?: NoReservedFields; itemType?: TailorAnyDBType; unitType?: TailorAnyDBType; storageLocationType?: TailorAnyDBType; } export function createInboundShipmentLineType>( params: CreateInboundShipmentLineTypeParams, ) { return db .table("InboundShipmentLine", { ...builtins(params), ...((params.fields ?? {}) as F), ...db.fields.timestamps(), }) .indexes({ fields: ["sourceDocumentType", "sourceDocumentId", "sourceLineId"], unique: false, name: "inbound_shipment_line_source_idx", }) .permission(defaultPermission) .gqlPermission(defaultGqlPermission); } export const inboundShipmentLine = createInboundShipmentLineType({});