fix(work-orders): persist completedDate without legacy GetWorkorderById

Save Draft failed on GetWorkorderById (HTTP 400) before EditWorkorder.
Post only Id + CompletedDate and cover the EditWorkorder route contract.
This commit is contained in:
Arthur Bassi 2026-07-31 09:37:10 -03:00
parent b2d44944ab
commit 96f3daf20c
6 changed files with 110 additions and 8 deletions

View file

@ -18,6 +18,7 @@ import {
mapUpdateDispatchPayload,
mapVendorDropdownItems,
mapWorkOrderDetail,
mapCompletedDateUpdateFormData,
mapWorkOrderFormToCreatePayload,
mapWorkOrderFormToUpdateFormData,
mapWorkOrderTableRow,
@ -307,6 +308,14 @@ export const workOrdersApi = {
);
},
/** Persist only CompletedDate via EditWorkorder — no GetWorkorderById prefetch. */
updateCompletedDate: async (id: string | number, completedDate: string): Promise<void> => {
await apiPostForm<{ message?: string; status?: string }>(
API_PATHS.workOrder.editWorkorder,
mapCompletedDateUpdateFormData(id, completedDate),
);
},
delete: async (id: string | number): Promise<void> => {
await apiDelete(API_PATHS.workOrder.deleteWorkorder, {
json: { Id: Number(id) },

View file

@ -405,6 +405,17 @@ export function mapWorkOrderFormToUpdateFormData(
return formData;
}
/** Partial EditWorkorder payload — only Id + CompletedDate (avoids legacy GetWorkorderById). */
export function mapCompletedDateUpdateFormData(
id: string | number,
completedDate: string,
): FormData {
const formData = new FormData();
formData.append("Id", String(id));
appendIfPresent(formData, "CompletedDate", completedDate);
return formData;
}
export function mapLocationOption(raw: unknown): LocationOption {
const item = asRecord(raw);
const name = readString(item, "name", "Name", "locationName", "LocationName");

View file

@ -12,10 +12,7 @@ import {
expandTablePatchToBoardFieldOps,
isLocalOnlyTablePatch,
} from "@/domain/work-orders/mappers/work-order-board-patch-mapper";
import {
mapWorkOrderDetailToFormValues,
mapWorkOrderTableRow,
} from "@/domain/work-orders/mappers/work-order-mapper";
import { mapWorkOrderTableRow } from "@/domain/work-orders/mappers/work-order-mapper";
import type {
WorkOrderTablePatch,
WorkOrderTableRow,
@ -37,9 +34,7 @@ type PatchResult =
{ kind: "local"; patch: WorkOrderTablePatch } | { kind: "board"; row: WorkOrderTableRow };
async function persistCompletedDate(id: string | number, completedDate: string): Promise<void> {
const detail = await workOrdersApi.getById(id);
const values = mapWorkOrderDetailToFormValues(detail);
await workOrdersApi.update(id, { ...values, completedDate });
await workOrdersApi.updateCompletedDate(id, completedDate);
}
async function applyBoardFieldOps(
@ -85,7 +80,7 @@ async function applyBoardFieldOps(
}
/** CompDoc completedDate uses EditWorkorder; board fields use PATCH …/board. */
async function runWorkOrderTablePatch(
export async function runWorkOrderTablePatch(
id: string | number,
patch: WorkOrderTablePatch,
getRow: ((id: string | number) => WorkOrderTableRow | undefined) | undefined,

View file

@ -165,6 +165,36 @@ describe("workOrdersApi.update", () => {
});
});
describe("workOrdersApi.updateCompletedDate", () => {
beforeEach(() => {
apiGet.mockReset();
apiPost.mockReset();
apiPostForm.mockReset();
apiPostForm.mockResolvedValue({ message: "Updated Successfully", status: "200" });
});
it("posts only Id and CompletedDate to EditWorkorder without GetWorkorderById", async () => {
await workOrdersApi.updateCompletedDate(55, "2026-07-30");
expect(apiGet).not.toHaveBeenCalled();
expect(apiPost).not.toHaveBeenCalled();
expect(apiPostForm).toHaveBeenCalledTimes(1);
expect(apiPostForm).toHaveBeenCalledWith(
API_PATHS.workOrder.editWorkorder,
expect.any(FormData),
);
expect(API_PATHS.workOrder.editWorkorder).toBe("WorkOrder/EditWorkorder");
expect(API_PATHS.workOrder.getById).toBe("WorkOrder/GetWorkorderById");
const formData = apiPostForm.mock.calls[0]?.[1] as FormData;
expect(formData.get("Id")).toBe("55");
expect(formData.get("CompletedDate")).toBe("2026-07-30");
expect(formData.get("Status")).toBeNull();
expect(formData.get("WorkerOrderTitle")).toBeNull();
expect(formData.getAll("ContactIds")).toEqual([]);
});
});
describe("workOrdersApi.fetchDispatchers", () => {
beforeEach(() => {
apiGet.mockReset();

View file

@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import {
mapCompletedDateUpdateFormData,
mapWorkOrderFormToCreatePayload,
mapWorkOrderFormToUpdateFormData,
} from "@/domain/work-orders/mappers/work-order-mapper";
@ -150,3 +151,24 @@ describe("mapWorkOrderFormToUpdateFormData", () => {
expect(formData.has("DocStatus")).toBe(false);
});
});
describe("mapCompletedDateUpdateFormData", () => {
it("builds FormData with only Id and CompletedDate", () => {
const formData = mapCompletedDateUpdateFormData(42, "2026-07-30");
expect(formData.get("Id")).toBe("42");
expect(formData.get("CompletedDate")).toBe("2026-07-30");
expect(formData.get("Status")).toBeNull();
expect(formData.get("WorkerOrderTitle")).toBeNull();
expect(formData.get("Description")).toBeNull();
expect(formData.getAll("ContactIds")).toEqual([]);
expect(formData.getAll("CategoryIds")).toEqual([]);
});
it("omits empty CompletedDate", () => {
const formData = mapCompletedDateUpdateFormData(1, " ");
expect(formData.get("Id")).toBe("1");
expect(formData.get("CompletedDate")).toBeNull();
});
});

View file

@ -0,0 +1,35 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const getById = vi.fn();
const update = vi.fn();
const updateCompletedDate = vi.fn();
vi.mock("@/domain/work-orders/api/work-orders-api", () => ({
workOrdersApi: {
getById: (...args: unknown[]) => getById(...args),
update: (...args: unknown[]) => update(...args),
updateCompletedDate: (...args: unknown[]) => updateCompletedDate(...args),
patchBoardField: vi.fn(),
},
}));
import { runWorkOrderTablePatch } from "@/domain/work-orders/use-cases/use-work-order-table-mutations";
describe("runWorkOrderTablePatch completedDate", () => {
beforeEach(() => {
getById.mockReset();
update.mockReset();
updateCompletedDate.mockReset();
updateCompletedDate.mockResolvedValue(undefined);
});
it("persists completedDate via updateCompletedDate without getById", async () => {
const result = await runWorkOrderTablePatch(99, { completedDate: "2026-07-30" }, undefined);
expect(getById).not.toHaveBeenCalled();
expect(update).not.toHaveBeenCalled();
expect(updateCompletedDate).toHaveBeenCalledTimes(1);
expect(updateCompletedDate).toHaveBeenCalledWith(99, "2026-07-30");
expect(result).toEqual({ kind: "local", patch: { completedDate: "2026-07-30" } });
});
});