diff --git a/src/domain/work-orders/api/work-orders-api.ts b/src/domain/work-orders/api/work-orders-api.ts index 88c26f45..ae08f8ad 100644 --- a/src/domain/work-orders/api/work-orders-api.ts +++ b/src/domain/work-orders/api/work-orders-api.ts @@ -396,19 +396,19 @@ export const workOrdersApi = { }); }, - addDispatchSignoff: async ( - dispatchId: string | number, - signoffType: string, - name: string, - signature: string, - signatureMethod: string, - ): Promise => { + addDispatchSignoff: async (params: { + dispatchId: string | number; + signoffType: string; + name: string; + signature: string; + signatureMethod: string; + }): Promise => { const data = await apiPost(API_PATHS.workOrder.addDispatchSignoff, { - DispatchId: dispatchId, - SignoffType: signoffType, - Name: name, - Signature: signature, - SignatureMethod: signatureMethod, + DispatchId: params.dispatchId, + SignoffType: params.signoffType, + Name: params.name, + Signature: params.signature, + SignatureMethod: params.signatureMethod, }); return mapDispatchSignoff(handleApiResponse(data)); }, diff --git a/src/domain/work-orders/mappers/doc-status-mapper.ts b/src/domain/work-orders/mappers/doc-status-mapper.ts new file mode 100644 index 00000000..90c9c016 --- /dev/null +++ b/src/domain/work-orders/mappers/doc-status-mapper.ts @@ -0,0 +1,28 @@ +import type { CompletionDocStatus } from "@/domain/work-orders/types/work-order-table-row"; + +/** UI uses `NN`; board/API enum uses `NotNeeded` (also numeric 3). */ +export function mapDocStatusToApi(value: string): string { + if (value === "NN") { + return "NotNeeded"; + } + return value; +} + +export function readDocStatusFromRecord(record: Record): CompletionDocStatus { + const rawValue = + record.docStatus ?? record.DocStatus ?? record.completionDoc ?? record.CompletionDoc; + if (typeof rawValue === "number") { + if (rawValue === 1) return "Yes"; + if (rawValue === 2) return "No"; + if (rawValue === 3) return "NN"; + } + if (typeof rawValue === "string") { + if (rawValue === "Yes" || rawValue === "No" || rawValue === "NN") { + return rawValue; + } + if (rawValue === "NotNeeded") { + return "NN"; + } + } + return ""; +} diff --git a/src/domain/work-orders/mappers/work-order-mapper.ts b/src/domain/work-orders/mappers/work-order-mapper.ts index eb7ea1e2..24fea36f 100644 --- a/src/domain/work-orders/mappers/work-order-mapper.ts +++ b/src/domain/work-orders/mappers/work-order-mapper.ts @@ -1,4 +1,9 @@ import { mapApiStatusToWizard } from "@/domain/work-orders/mappers/wizard-draft-mapper"; +import { + mapDocStatusToApi, + readDocStatusFromRecord, +} from "@/domain/work-orders/mappers/doc-status-mapper"; +import type { UpliftRequest } from "@/domain/uplifts/types/uplift"; import type { DispatchChecklistItem, DispatchComment, @@ -17,6 +22,8 @@ import type { WorkOrderFormValues, WorkOrderListItem, } from "@/domain/work-orders/types/work-order"; +import type { WorkOrderStatus } from "@/domain/work-orders/types/work-order-common"; +import { WORK_ORDER_STATUS_OPTIONS } from "@/domain/work-orders/types/work-order-common"; import type { CompletionDocStatus, WorkOrderTableRow, @@ -24,11 +31,10 @@ import type { import type { WOType } from "@/domain/work-orders/types/work-order-wizard"; import { deriveDayFields } from "@/domain/work-orders/utils/table-day-utils"; import { formatApptRange } from "@/domain/work-orders/utils/wizard-date-utils"; -import type { UpliftRequest } from "@/domain/uplifts/types/uplift"; -import type { WorkOrderStatus } from "@/domain/work-orders/types/work-order-common"; -import { WORK_ORDER_STATUS_OPTIONS } from "@/domain/work-orders/types/work-order-common"; import { toDateInputValue } from "@/lib/time-utils"; +export { mapDocStatusToApi }; + function asRecord(raw: unknown): Record { return typeof raw === "object" && raw !== null ? (raw as Record) : {}; } @@ -118,30 +124,8 @@ function readWoType(record: Record): WOType | "" { return ""; } -/** UI uses `NN`; board/API enum uses `NotNeeded` (also numeric 3). */ -export function mapDocStatusToApi(value: string): string { - if (value === "NN") { - return "NotNeeded"; - } - return value; -} - function readDocStatus(record: Record): CompletionDocStatus { - const rawValue = - record.docStatus ?? record.DocStatus ?? record.completionDoc ?? record.CompletionDoc; - if (typeof rawValue === "number") { - if (rawValue === 1) return "Yes"; - if (rawValue === 2) return "No"; - if (rawValue === 3) return "NN"; - } - const raw = readString(record, "docStatus", "DocStatus", "completionDoc", "CompletionDoc"); - if (raw === "Yes" || raw === "No" || raw === "NN") { - return raw; - } - if (raw === "NotNeeded") { - return "NN"; - } - return ""; + return readDocStatusFromRecord(record); } export function mapWorkOrderTableRow(raw: unknown): WorkOrderTableRow { diff --git a/src/domain/work-orders/use-cases/use-work-order-mutations.ts b/src/domain/work-orders/use-cases/use-work-order-mutations.ts index 5c69e3a4..942a048b 100644 --- a/src/domain/work-orders/use-cases/use-work-order-mutations.ts +++ b/src/domain/work-orders/use-cases/use-work-order-mutations.ts @@ -263,7 +263,13 @@ export function useAddDispatchSignoff( return useMutation({ mutationFn: ({ signoffType, name, signature, signatureMethod }: AddDispatchSignoffInput) => - workOrdersApi.addDispatchSignoff(dispatchId, signoffType, name, signature, signatureMethod), + workOrdersApi.addDispatchSignoff({ + dispatchId, + signoffType, + name, + signature, + signatureMethod, + }), onSuccess: (_data, variables) => { void queryClient.invalidateQueries({ queryKey: queryKeys.workOrders.dispatch(dispatchId) }); toast.success(`${variables.signoffType} sign-off collected`); diff --git a/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx b/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx index 8f4117b8..1ac5add6 100644 --- a/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx +++ b/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx @@ -72,7 +72,6 @@ const BASE_DETAIL: WorkOrderDetail = { describe("useWorkOrderTableMutations completion-doc persistence", () => { let serverState: WorkOrderDetail; let events: string[]; - let lastBoardPatch: { field: string; value?: string | null; workOrderVersion: string } | null; beforeEach(() => { getById.mockReset(); @@ -83,7 +82,6 @@ describe("useWorkOrderTableMutations completion-doc persistence", () => { patchBoardField.mockReset(); serverState = { ...BASE_DETAIL }; events = []; - lastBoardPatch = null; resolveBoardWorkOrderVersion.mockImplementation(async () => { events.push("resolveVersion:start"); @@ -92,19 +90,25 @@ describe("useWorkOrderTableMutations completion-doc persistence", () => { return "AAAAAAA="; }); - patchBoardField.mockImplementation(async (_id: unknown, payload: typeof lastBoardPatch) => { - events.push("boardPatch:start"); - await delay(5); - lastBoardPatch = payload; - if (payload?.field === "docStatus" && typeof payload.value === "string") { - serverState = { - ...serverState, - docStatus: - payload.value === "NotNeeded" ? "NN" : (payload.value as WorkOrderDetail["docStatus"]), - }; - } - events.push("boardPatch:end"); - }); + patchBoardField.mockImplementation( + async ( + _id: unknown, + payload: { field: string; value?: string | null; workOrderVersion: string }, + ) => { + events.push("boardPatch:start"); + await delay(5); + if (payload.field === "docStatus" && typeof payload.value === "string") { + serverState = { + ...serverState, + docStatus: + payload.value === "NotNeeded" + ? "NN" + : (payload.value as WorkOrderDetail["docStatus"]), + }; + } + events.push("boardPatch:end"); + }, + ); getById.mockImplementation(async () => { events.push("getById:start");