//#region MMReceiveLaborTicket /** * Represents a labor ticket as received from the MM API /erp/v1/labor-tickets/export/updates */ export class MMReceiveLaborTicket { constructor(data: Partial) { Object.assign(this, data); } // Returns the closed date if it is a valid date, otherwise returns null get workOrderOperationClosedDate(): string | null { const closedDate = this.workOrderOperation?.closedDate; return typeof closedDate === "string" && closedDate !== "" && !isNaN(Date.parse(closedDate)) ? closedDate : null; } set workOrderOperationClosedDate(value: string | null) { if (this.workOrderOperation) { this.workOrderOperation.closedDate = value; } } // Returns 1 if the work order operation is closed (has a valid closed date), 0 otherwise get workOrderOpIsClosed(): number { return this.workOrderOperationClosedDate !== null ? 1 : 0; } /*Descriptions from machinemetrics.atlassian.net/wiki/spaces/DEVE/pages/842661901/MM+ERP+Schema+Descriptions*/ badParts!: number; // The number of parts produced that do not meet quality standards clockIn!: string | null; // The timestamp when the work on this ticket started clockOut!: string | null; // The timestamp when the work on this ticket ended comment!: string | null; createdAt!: string | null; goodParts!: number; // The number of parts produced that meet quality standards laborTicketId!: string; // The unique identifier for the labor ticket in the ERP laborTicketRef!: string; // The unique identifier for the labor ticket in MM /** Set on real-time NATS payloads; typically absent on ERP-imported tickets */ machineRef?: string | null; lot!: string; // Refers to a material batch. If not available in the ERP, default to an empty string personId!: string; // The person who did the work reasons?: MMReceiveLaborTicketReason[]; resourceId!: string; // The physical resource that did the work resource?: { name: string }; // The resource name (available from export/updates endpoint) sequenceNumber!: number; // Which sequence this operation is for in the order, associates back to a part_operation with the part_number from the work_order, and sequence_number from the op split!: string; // Batch number if order split for staggered delivery. If not available in the ERP, default to an empty string state!: string; // The current state of the labor ticket (e.g., "CLOSED/OPEN/CANCELLED") type!: string; // If the labor is production, setup, or indirect syncedAt!: string | null; updatedAt!: string | null; workOrderId!: string; // The order this labor ticket corresponds to workOrderOperation?: MMReceiveLaborTicketWorkOrderOperation; sub!: string; // Batch number for parts that had to be rerun. If not available in the ERP, default to an empty string transactionDate!: string | null; customFieldsSchemaRef!: number | null; customFields!: Record | null; } /** * Represents a reason in the MMApiReceiveLaborTicket object as received from MM */ export interface MMReceiveLaborTicketReason { reason: { annotationTypeRef: string | null; category: string; // Parent group if applicable (optional) code: string; // The functional name of the label companyId: string; createdAt: string; description: string; entityType: string; // Whether it represents machine downtime or rejected parts context (downtime/quality) reasonId: string; // Unique identifier in the ERP reasonRef: number; rejectReasonRef: number; updatedAt: string | null; }; } /** * Represents a work order operation in the MMApiReceiveLaborTicket object, incomplete when * pulling updated labor tickets from MM. NATS payloads may add custom fields and closure fields. */ export interface MMReceiveLaborTicketWorkOrderOperation { closedDate: string | null; // non-null and a valid date if the work order operation is closed /** When set (e.g. from MM export), used when building labor-ticket WOO sync payloads for non-close updates */ status?: string | null; customFieldsSchemaRef?: number | null; customFields?: Record | null; } //#endregion MMReceiveLaborTicket //#region MMReceiveWorkOrder /** * Represents a work order as received from the MM GraphQL API (erpWorkOrders) */ export class MMReceiveWorkOrder { constructor(data: Partial) { Object.assign(this, data); } companyId!: string; workOrderId!: string; lot!: string; split!: string; sub!: string; status!: string; dueDate!: string | null; description!: string; scheduledStartDate!: string | null; scheduledEndDate!: string | null; closedDate!: string | null; quantityRequired!: number; partNumber!: string; partRevision!: string; method!: string; createdAt!: string; updatedAt!: string; customFieldsSchemaRef!: number | null; customFields!: Record | null; } //#endregion MMReceiveWorkOrder //#region MMReceiveWorkOrderOperation /** * Represents a work order operation as received from the MM GraphQL API * (erpWorkOrderOperations). Field names match the REST import payload * ({@code MMSendWorkOrderOperation}) one-to-one, including MM's lowercase-`b` * burden-rate spellings. */ export class MMReceiveWorkOrderOperation { constructor(data: Partial) { Object.assign(this, data); } companyId!: string; workOrderId!: string; lot!: string; split!: string; sub!: string; /** Stored numerically by MM; exposed as the string form the REST import uses. */ sequenceNumber!: string; resourceId!: string; /** * Numeric columns are nullable in MM; `null` means "not provided by the ERP", which is * distinct from a real 0. Values MM returns that don't parse to a finite number are * also reported as `null`. */ startQuantity!: number | null; finishQuantity!: number | null; expectedRejectRate!: number | null; scheduledStartDate!: string | null; scheduledFinishDate!: string | null; closedDate!: string | null; cycleTimeMs!: number | null; setupTimeMs!: number | null; productionburdenRateHourly!: number | null; setupburdenRatehourly!: number | null; operationType!: string; quantityPerPart!: number | null; status!: string; createdAt!: string; updatedAt!: string; customFieldsSchemaRef!: number | null; customFields!: Record | null; } //#endregion MMReceiveWorkOrderOperation //#region MMReceiveTimesheet /** * Represents a timesheet row as received from the MM API /erp/v1/timesheets/updates * (employee clock in/out export to ERP). */ export class MMReceiveTimesheet { constructor(data: Partial) { Object.assign(this, data); } /** MM reference for this timesheet row (used for ordering and dedupe in sync) */ timesheetRef!: number | string; /** Optional MM identifier when present */ timesheetId?: string | number | null; /** ERP employee / person id (e.g. Epicor EmployeeNum) */ personId!: string; /** ISO timestamp when the employee clocked out; null while still clocked in */ clockOut!: string | null; clockIn?: string | null; createdAt?: string | null; updatedAt?: string | null; syncedAt?: string | null; } //#endregion MMReceiveTimesheet //#region MMReceiveDispatchPriority /** * One row of MM's `erpWorkOrderOperationDispatchPriorities` table as returned by * `MMApiClient.fetchDispatchPrioritiesFromGraphQL()`. `sequenceNumber` is exposed as the * string form the other receive models use ({@link MMReceiveWorkOrderOperation}). */ export class MMReceiveDispatchPriority { constructor(data: Partial) { Object.assign(this, data); } /** MM's surrogate primary key (bigint). */ dispatchPriorityRef!: number; companyId!: string; /** Nullable in MM; the SDK write path always fills it, other writers may not. */ authorityOperationId!: string | null; scopeResourceId!: string; workOrderId!: string; sequenceNumber!: string; lot!: string; split!: string; sub!: string; preallocatedMachineResourceId!: string | null; priority!: number; createdAt!: string; updatedAt!: string; customFieldsSchemaRef!: number | null; customFields!: Record | null; } //#endregion MMReceiveDispatchPriority