import type { WorkOrderBoardCreatePayload, WorkOrderTypeApi, } from "@/domain/work-orders/types/work-order-board"; import { LIFECYCLE_STATUS_API, WORK_ORDER_TYPE_API, } from "@/domain/work-orders/types/work-order-board"; import type { WizardWOStatus, WOType, WorkOrderWizardDraft, } from "@/domain/work-orders/types/work-order-wizard"; import { fmtDateRange } from "@/domain/work-orders/utils/wizard-date-utils"; import { assignWizardScheduleFields } from "@/domain/work-orders/mappers/assign-wizard-schedule-fields"; import { assignWizardVendorApptFields } from "@/domain/work-orders/mappers/assign-wizard-vendor-appt-fields"; import { assignWizardServicePocFields } from "@/domain/work-orders/mappers/assign-wizard-service-poc-fields"; import { resolveIsAddOnForCreate } from "@/domain/work-orders/utils/wo-addon-cutoff"; const WO_TYPE_TO_API: Record = { PM: WORK_ORDER_TYPE_API.PM, Emergency: WORK_ORDER_TYPE_API.Emergency, Reactive: WORK_ORDER_TYPE_API.Reactive, Overdue: WORK_ORDER_TYPE_API.Overdue, }; /** Leading token of a location label, e.g. `BK5` from `BK5 · Dallas` or `CHI-1042` from `CHI-1042 — Chicago`. */ export function parseSiteCodeFromLocationName(name: string): string { const trimmed = name.trim(); if (!trimmed) { return ""; } const match = trimmed.match(/^([A-Za-z0-9-]+)/); return match?.[1] ?? ""; } export function resolveSiteCode(option: { siteCode?: string; name?: string; }): string { if (option.siteCode?.trim()) { return option.siteCode.trim(); } return parseSiteCodeFromLocationName(option.name ?? ""); } export function mapWizardTypeToApi(type: WOType | ""): WorkOrderTypeApi | null { if (!type) { return null; } return WO_TYPE_TO_API[type]; } /** * Legacy/general description only. * Service notes, extras, POC, and vendor notes are sent as structured fields. */ export function buildBoardDescription(draft: WorkOrderWizardDraft): string { const parts: string[] = []; if (draft.schedMode === "range" && draft.scheduledOn && draft.scheduleEnd) { parts.push(`Schedule range: ${fmtDateRange(draft.scheduledOn, draft.scheduleEnd)}`); } return parts.join("\n"); } export function mapWizardDraftToBoardCreatePayload( draft: WorkOrderWizardDraft, ): WorkOrderBoardCreatePayload { const workOrderType = mapWizardTypeToApi(draft.type || "PM"); const siteCode = draft.siteCode.trim() || resolveSiteCode({ name: draft.locationName }); if (workOrderType === null) { throw new Error("Work order type is required"); } if (!siteCode) { throw new Error("Site code is required"); } const payload: WorkOrderBoardCreatePayload = { workOrderType, siteCode, // Range start persists as scheduledDate (prototype hasScheduleDate). Use it for // the create-time Add-On cutoff hint; week mode uses targetWeek / Monday. isAddOn: resolveIsAddOnForCreate({ scheduledOn: draft.scheduleWeekOnly ? draft.targetWeek?.trim() || draft.scheduledOn : draft.scheduledOn, manualOverride: draft.isAddOnOverride, }), }; if (draft.status) { payload.lifecycleStatus = LIFECYCLE_STATUS_API[draft.status as WizardWOStatus]; } if (draft.woNumber.trim()) { payload.woNumber = draft.woNumber.trim(); } if (draft.assigneeId.trim()) { payload.assignTo = draft.assigneeId.trim(); } assignWizardScheduleFields(payload, draft); assignWizardVendorApptFields(payload, draft); assignWizardServicePocFields(payload, draft); const description = buildBoardDescription(draft); if (description) { payload.description = description; } const locationId = draft.locationId.trim() ? Number(draft.locationId) : NaN; if (Number.isFinite(locationId)) { payload.locationId = locationId; } return payload; }