import { MMReceiveLaborTicket } from "../services/mm-api-service/types/receive-types.js"; import { convertUtcDateTimeToErpLocal, getERPTimezone } from "./erp-timezone-utils.js"; /** * Converts key datetime fields from UTC (MachineMetrics API) to the ERP's local timezone. * All inputs/outputs are ISO-8601 strings, and invalid inputs throw errors. * @param laborTicket The MMApiReceiveLaborTicket object to convert */ export function convertLaborTicketToLocalTimezone( laborTicket: MMReceiveLaborTicket ): MMReceiveLaborTicket { const timeFields = [ "clockIn", "clockOut", "transactionDate", "createdAt", "updatedAt", "workOrderOperationClosedDate", ] as const; const timezone = getERPTimezone(); timeFields.forEach((field) => { const value = laborTicket[field]; if (value) { laborTicket[field] = convertUtcDateTimeToErpLocal(value, timezone); } else { laborTicket[field] = null; } }); return laborTicket; } /** * Returns a localized COPY of the labor ticket for handing to connector code, * leaving the original ticket's UTC datetime values untouched. Needed on paths * that write the ticket back to MM after the ERP call (e.g. the real-time NATS * listener): {@link convertLaborTicketToLocalTimezone} mutates in place — * including `workOrderOperation.closedDate` via the `workOrderOperationClosedDate` * setter — so converting the original would corrupt the UTC values MM requires. * * The clone is shallow, plus a shallow copy of `workOrderOperation` (the one * nested object the localization mutates). That isolates every field the SDK * itself rewrites — the datetime values are immutable strings — but other * nested references (e.g. `customFields`, `reasons`) remain shared with the * original. As on the polling path, connector handlers must treat the ticket * as read-only input; mutating shared nested objects would leak into the MM * write-back. */ export function localizeLaborTicketCopyForConnector( laborTicket: MMReceiveLaborTicket ): MMReceiveLaborTicket { const copy = new MMReceiveLaborTicket({ ...laborTicket, workOrderOperation: laborTicket.workOrderOperation ? { ...laborTicket.workOrderOperation } : laborTicket.workOrderOperation, }); return convertLaborTicketToLocalTimezone(copy); }