import type { MMWorkOrderOperationStatusValue, MMWorkOrderStatusValue, } from "./erp-types.js"; /** * Canonical representation of a flattened work order row that contains the * information needed to build MM work order entities plus their operations. * * All properties are optional to maintain backwards compatibility with * existing connectors. * * Custom fields: one row fans out to up to four MM entities, so the `*CustomFields` / * `*CustomFieldsSchemaRef` pairs below are scoped per entity. For all of them, leaving a * property `undefined` keeps the value MM already holds, and `null` clears it. Parts, part * operations, and work orders are deduplicated across rows, so their values are resolved * across every row of the entity: a non-null value wins over `null`, which wins over * `undefined`, and between differing non-null values the first row wins. Each pair resolves * together, so the winning row supplies both the values and the schema ref they were written * against and the two are never taken from different rows. */ export interface FlattenedWorkOrderPartFields { /** ERP part number (required for Parts when present). */ partNumber?: string | number; /** ERP part revision or version string. */ partRevision?: string | number; /** Routing/method identifier (defaults to "Standard" when omitted). */ method?: string; /** * `customFields` for the MM part. Parts are deduplicated across every row in the batch, * all work orders included, so a part's rows should agree on this value. */ partCustomFields?: Record | null; /** `customFieldsSchemaRef` for the MM part. */ partCustomFieldsSchemaRef?: number | null; } /** * Fields that land on the MM **part operation**: the routing step for a part, shared by every * work order that runs that part. These are deduplicated by part and sequence number across the * entire batch, so nothing here may vary per work order. * * Naming trap: `operationDescription` belongs to this group, so it describes the routing step and * not the work order operation. The name predates the typed row and several connectors alias it * directly in SQL (`... AS operationDescription`), where a rename would fail silently rather than * at compile time, so it is kept as-is. Within this type, `op*` reliably means the work order * operation; a bare `operation*` prefix does not reliably mean anything. * * Several properties here are read a second time for the work order operation: `sequenceNumber`, * `resourceId`, `cycleTimeMs`, `setupTimeMs`, and `quantityPerPart`. One row property can * therefore feed two MM entities. */ export interface FlattenedWorkOrderPartOperationFields { /** Sequence number of the operation on the routing. */ sequenceNumber?: string | number; /** Resource or machine identifier responsible for the operation. */ resourceId?: string | number; /** Operation cycle time expressed in milliseconds. */ cycleTimeMs?: number; /** Operation setup time expressed in milliseconds. */ setupTimeMs?: number; /** * Human-readable description of the routing step. Lands on the MM part operation as * `description`, not on the work order operation, despite the `operation` prefix. Legacy * name kept for compatibility; see the note on this interface. */ operationDescription?: string; /** Quantity of parts operated on per cycle. */ quantityPerPart?: number; /** Display name of the part, stored on the part operation (`partName` in MM). */ partName?: string; /** * `customFields` for the MM part operation (the routing step). Part operations are * deduplicated across every row in the batch, all work orders included, so data that varies * per work order belongs on `opCustomFields` instead. */ partOperationCustomFields?: Record | null; /** `customFieldsSchemaRef` for the MM part operation. */ partOperationCustomFieldsSchemaRef?: number | null; } /** * Fields that land on the MM **work order**: deduplicated by MM's full work order identity of * id, lot, split, and sub, so every row of one work order should agree on them, while two lots * of one id stay separate entities that resolve their custom fields independently. Extends the * part group because a work order carries the * identity of the part it runs, which is why `partNumber`, `partRevision`, and `method` serve * both entities. * * The operation-level counterparts of `status`, `scheduledStartDate`, and `closedDate` live in * {@link FlattenedWorkOrderOperationFields} under the `op*` prefix. */ export interface FlattenedWorkOrderFields extends FlattenedWorkOrderPartFields { /** Unique identifier for the work order in the ERP. */ workOrderId?: string | number; /** Lot number (if the ERP distinguishes lots). */ lot?: string | number; /** Split identifier (if the ERP splits orders). */ split?: string | number; /** Sub identifier (for multi-level orders). */ sub?: string | number; /** * Work order status — one of `MMWorkOrderStatus` (e.g. RELEASED, ACTIVE, COMPLETED). * Required in practice: `syncWorkOrderBatchFromFlattened` fails the batch when a work * order has no status. */ status?: MMWorkOrderStatusValue; /** * Due date expressed as an ISO-8601 UTC string (trailing `Z` or explicit offset). * The SDK validates but does not shift timezones. */ dueDate?: string; /** Free-form description of the work order. */ description?: string; /** Scheduled start datetime in ISO-8601 UTC form. */ scheduledStartDate?: string; /** Scheduled end datetime in ISO-8601 UTC form. */ scheduledEndDate?: string; /** Closed datetime in ISO-8601 UTC form. */ closedDate?: string; /** Quantity required by the work order. */ quantityRequired?: number; /** `customFields` for the MM work order. Rows for the same work order should agree on this value. */ workOrderCustomFields?: Record | null; /** `customFieldsSchemaRef` for the MM work order. */ workOrderCustomFieldsSchemaRef?: number | null; } /** * Fields that land on the MM **work order operation**: one per row, never deduplicated, so these * may vary freely between rows of the same work order. * * Prefix convention: `op*` distinguishes a field from its work-order-level counterpart, as in * `opStatus` against `status` and `opClosedDate` against `closedDate`. `operationType` is a * legacy exception that uses the longer prefix while still belonging to this group. Because * `operation*` therefore spans two different MM entities, new fields here use `op*`. */ export interface FlattenedWorkOrderOperationFields { /** Work order identifier (repeated for each operation). */ workOrderId?: string | number; /** Lot identifier for the operation row. */ lot?: string | number; /** Split identifier for the operation row. */ split?: string | number; /** Sub identifier for the operation row. */ sub?: string | number; /** Sequence number for the specific operation. */ sequenceNumber?: string | number; /** Resource or machine identifier for the operation. */ resourceId?: string | number; /** Quantity started on the operation. */ startQuantity?: number; /** Quantity finished on the operation. */ finishQuantity?: number; /** Expected reject percentage (0-1). */ expectedRejectRate?: number; /** Scheduled start datetime (ISO-8601 UTC). */ opScheduledStartDate?: string; /** Scheduled finish datetime (ISO-8601 UTC). */ opScheduledFinishDate?: string; /** Closed datetime for the operation (ISO-8601 UTC). */ opClosedDate?: string; /** Production burden rate per hour. */ productionburdenRateHourly?: number | string; /** Setup burden rate per hour. */ setupburdenRatehourly?: number | string; /** * Operation type (Production, Setup, etc.). Belongs to the work order operation despite sharing * the `operation` prefix with `operationDescription`, which belongs to the part operation. */ operationType?: string; /** Quantity per part for the operation. */ quantityPerPart?: number; /** * Operation status — one of `MMWorkOrderOperationStatus`. Falls back to the row's * work order `status` when omitted; the batch fails if neither is present. */ opStatus?: MMWorkOrderOperationStatusValue; /** * `customFields` for the MM work order operation. MM replaces the object wholesale, so * include every key the operation should keep, including any the labor-ticket path writes. */ opCustomFields?: Record | null; /** `customFieldsSchemaRef` for the MM work order operation. */ opCustomFieldsSchemaRef?: number | null; } export type FlattenedWorkOrderRowBase = FlattenedWorkOrderPartFields & FlattenedWorkOrderPartOperationFields & FlattenedWorkOrderFields & FlattenedWorkOrderOperationFields; /** * Canonical flattened row that callers pass into * `StandardProcessDrivers.syncWorkOrderBatchFromFlattened`. */ export type FlattenedWorkOrderRow = FlattenedWorkOrderRowBase;