import { type CommonReservedFields, type NoReservedFields, defaultGqlPermission, defaultPermission, } from "@tailor-platform/erp-kit/core"; import { db, type TailorAnyDBField, type TailorAnyDBType } from "@tailor-platform/sdk"; import { stockReservationLifecycle } from "./stockReservation.lifecycle.generated"; import { storageLocation } from "./storageLocation"; export const RESERVATION_SOURCE_TYPES = ["SALES_ORDER", "TRANSFER_ORDER"] as const; const builtins = (params: { itemType?: TailorAnyDBType; siteType?: TailorAnyDBType }) => { const itemId = db.uuid().description("Foreign key to Item"); const siteId = db.uuid().description("Site where stock is reserved"); return { sourceType: db .enum(RESERVATION_SOURCE_TYPES) .description("Source document type: SALES_ORDER or TRANSFER_ORDER"), sourceId: db .uuid() .description("ID of the source document. Generic reference; not a typed foreign key."), sourceLineId: db .uuid() .description( "ID of the source-document line. Non-unique trace key; one source line may create multiple ATP reservation slices.", ), itemId: params.itemType ? itemId.relation({ type: "n-1", toward: { type: params.itemType, as: "item" }, backward: "stockReservations", }) : itemId, siteId: params.siteType ? siteId.relation({ type: "n-1", toward: { type: params.siteType, as: "site" }, }) : siteId, storageLocationId: db .uuid({ optional: true }) .relation({ type: "n-1", toward: { type: storageLocation, as: "storageLocation" }, backward: "stockReservations", }) .description("Optional allocated storage location within the site"), reservedQuantity: db .decimal() .description("Reserved demand quantity for this ATP reservation slice"), consumedQuantity: db .decimal() .description("Cumulative quantity consumed by shipment or issue against this reservation"), status: db .enum(stockReservationLifecycle.states) .description( "Reservation lifecycle status: OPEN while reservation demand remains, CLOSED when it no longer contributes to ATP", ), requiredDate: db.date().description("Demand date from the source line"), }; }; type ReservedFields = keyof ReturnType | CommonReservedFields; export interface CreateStockReservationTypeParams> { fields?: NoReservedFields; itemType?: TailorAnyDBType; siteType?: TailorAnyDBType; } export function createStockReservationType>( params: CreateStockReservationTypeParams, ) { return db .table("StockReservation", { ...builtins(params), ...((params.fields ?? {}) as F), ...db.fields.timestamps(), }) .indexes({ fields: ["sourceType", "sourceLineId"], unique: false, name: "stock_reservation_source_idx", }) .permission(defaultPermission) .gqlPermission(defaultGqlPermission); } export const stockReservation = createStockReservationType({});