shoc-frontend-new/src/domain/work-orders/mappers/wizard-draft-mapper.ts
Arthur Bassi b7056f569e fix(work-orders): persist completion doc fields without race
Map docStatus through the real update payload, serialize concurrent
table patches per work order, and split CompDoc UI for governance.
2026-07-28 12:49:51 -03:00

123 lines
3.4 KiB
TypeScript

import type { WorkOrderFormValues } from "@/domain/work-orders/types/work-order-detail";
import type {
WOType,
WizardWOStatus,
WorkOrderWizardDraft,
} from "@/domain/work-orders/types/work-order-wizard";
import type { WorkOrderStatus } from "@/domain/work-orders/types/work-order-common";
import { formatApptRange, todayIso } from "@/domain/work-orders/utils/wizard-date-utils";
const WIZARD_TO_API_STATUS: Record<WizardWOStatus, WorkOrderStatus> = {
Incomplete: "Open",
Pending: "Open",
Scheduled: "Open",
"En Route": "In Progress",
"On Site": "In Progress",
"In Progress": "In Progress",
Completed: "Done",
Rescheduled: "On Hold",
"Pending Quote": "On Hold",
};
const API_TO_WIZARD_STATUS: Partial<Record<WorkOrderStatus, WizardWOStatus>> = {
Open: "Incomplete",
"In Progress": "In Progress",
"On Hold": "Pending",
Done: "Completed",
};
const TYPE_TO_PRIORITY: Record<WOType, string> = {
Emergency: "Sev 1",
Reactive: "Sev 2",
Overdue: "Sev 2",
"Add-On": "Sev 3",
PM: "Sev 3",
};
export function mapWizardStatusToApi(status: WizardWOStatus | ""): WorkOrderStatus {
if (!status) {
return "Open";
}
return WIZARD_TO_API_STATUS[status] ?? "Open";
}
export function mapApiStatusToWizard(status: string): WizardWOStatus | "" {
if (!status) {
return "";
}
if (API_TO_WIZARD_STATUS[status as WorkOrderStatus]) {
return API_TO_WIZARD_STATUS[status as WorkOrderStatus]!;
}
const wizardStatuses = Object.keys(WIZARD_TO_API_STATUS) as WizardWOStatus[];
if (wizardStatuses.includes(status as WizardWOStatus)) {
return status as WizardWOStatus;
}
if (status === "Canceled" || status === "Cancelled") {
return "Canceled" as WizardWOStatus;
}
return "Incomplete";
}
export function mapTypeToPriority(type: WOType | ""): string {
if (!type) {
return "Sev 3";
}
return TYPE_TO_PRIORITY[type];
}
function buildTitle(draft: WorkOrderWizardDraft): string {
if (draft.woNumber) {
return `${draft.type || "Work Order"} — #${draft.woNumber}`;
}
if (draft.locationName) {
return `${draft.type || "Work Order"} — ${draft.locationName}`;
}
return draft.type || "Work Order";
}
function buildDescription(draft: WorkOrderWizardDraft): string {
const parts: string[] = [];
if (draft.pocNotes) {
parts.push(`POC notes: ${draft.pocNotes}`);
}
if (draft.pocName || draft.pocPhone) {
parts.push(`POC: ${[draft.pocName, draft.pocPhone].filter(Boolean).join(" · ")}`);
}
if (draft.apptStart) {
parts.push(`Appt: ${formatApptRange(draft.apptStart, draft.apptEnd)}`);
}
if (draft.vendorNotes) {
parts.push(`Vendor notes: ${draft.vendorNotes}`);
}
if (draft.vendorName) {
parts.push(`Vendor: ${draft.vendorName}`);
}
return parts.join("\n");
}
export function mapWizardDraftToFormValues(draft: WorkOrderWizardDraft): WorkOrderFormValues {
return {
internalWONumber: "",
workOrderNumber: draft.woNumber,
title: buildTitle(draft),
locationId: draft.locationId,
priority: mapTypeToPriority(draft.type),
status: mapWizardStatusToApi(draft.status),
createdDate: todayIso(),
dueDate: draft.dueDate,
scheduledDate: draft.scheduleWeekOnly ? "" : draft.scheduledOn,
completedDate: "",
docStatus: "",
assignedTo: draft.assigneeName,
description: buildDescription(draft),
po: "",
tt: "",
problem: draft.pm,
trade: "",
subTrade: "",
vendorNTE: "",
source: draft.type,
};
}