import { type CommonReservedFields, type NoReservedFields, defaultGqlPermission, defaultPermission, } from "@tailor-platform/erp-kit/core"; import { db, type TailorAnyDBField, type TailorAnyDBType } from "@tailor-platform/sdk"; import { outboundShipment } from "./outboundShipment"; // Line-level source document types for outbound shipments. export const OUTBOUND_SHIPMENT_LINE_SOURCE_DOCUMENT_TYPES = ["SALES_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 { outboundShipmentId: db .uuid() .relation({ type: "n-1", toward: { type: outboundShipment, as: "outboundShipment" }, backward: "lines", }) .description("Foreign key to OutboundShipment header"), itemId: params.itemType ? itemId.relation({ type: "n-1", toward: { type: params.itemType, as: "item" }, backward: "outboundShipmentLines", }) : 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: "outboundShipmentLines", }) : 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: "primaryOutboundShipmentLines", }) : primaryUnitId, unitConversionRate: db .decimal() .description("Multiplier used to convert quantity into primaryQuantity"), storageLocationId: params.storageLocationType ? storageLocationId.relation({ type: "n-1", toward: { type: params.storageLocationType, as: "storageLocation" }, backward: "outboundShipmentLines", }) : storageLocationId, stockType: db .enum([...STOCK_TYPES] as [string, ...string[]]) .description("Stock type affected by this line"), sourceDocumentType: db .enum(OUTBOUND_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 CreateOutboundShipmentLineTypeParams> { fields?: NoReservedFields; itemType?: TailorAnyDBType; unitType?: TailorAnyDBType; storageLocationType?: TailorAnyDBType; } export function createOutboundShipmentLineType>( params: CreateOutboundShipmentLineTypeParams, ) { return db .table("OutboundShipmentLine", { ...builtins(params), ...((params.fields ?? {}) as F), ...db.fields.timestamps(), }) .indexes({ fields: ["sourceDocumentType", "sourceDocumentId", "sourceLineId"], unique: false, name: "outbound_shipment_line_source_idx", }) .permission(defaultPermission) .gqlPermission(defaultGqlPermission); } export const outboundShipmentLine = createOutboundShipmentLineType({});