fix(work-orders): keep explicit wizard status picks on dated drafts

Derive Scheduled or Pending only when the patch touches schedule fields, matching the board path.
This commit is contained in:
Arthur Bassi 2026-09-03 14:42:19 -03:00
parent 9fc67516ca
commit 3a8f41a444
3 changed files with 58 additions and 5 deletions

View file

@ -173,7 +173,7 @@ export function withAutoScheduleStatus<T extends ScheduleDateInput & { status?:
schedulePatch: Partial<T> & ScheduleDateInput,
): Partial<T> {
const next = {
status: current.status ?? "",
status: schedulePatch.status ?? current.status ?? "",
scheduledOn:
schedulePatch.scheduledOn !== undefined ? schedulePatch.scheduledOn : current.scheduledOn,
scheduleWeekOnly:
@ -181,6 +181,9 @@ export function withAutoScheduleStatus<T extends ScheduleDateInput & { status?:
? schedulePatch.scheduleWeekOnly
: current.scheduleWeekOnly,
};
if (!patchTouchesSchedule(schedulePatch as WorkOrderTablePatch)) {
return { ...schedulePatch };
}
return { ...schedulePatch, ...maybeAutoSchedulePatch(next) };
}

View file

@ -60,13 +60,13 @@ describe("WizardStepVendorTime creation statuses (AAP)", () => {
});
it("allows selecting a non-Completed status", () => {
const onUpdate = vi.fn();
const onPatch = vi.fn();
render(
<WizardStepVendorTime
draft={{ ...EMPTY_WIZARD_DRAFT, type: "PM", status: "Incomplete" }}
vendors={[]}
onUpdate={onUpdate}
onPatch={vi.fn()}
onUpdate={vi.fn()}
onPatch={onPatch}
/>,
);
@ -74,6 +74,28 @@ describe("WizardStepVendorTime creation statuses (AAP)", () => {
const menu = screen.getByRole("button", { name: /^pending$/i }).closest("div");
expect(menu).not.toBeNull();
fireEvent.click(within(menu!.parentElement!).getByRole("button", { name: /^pending$/i }));
expect(onUpdate).toHaveBeenCalledWith("status", "Pending");
expect(onPatch).toHaveBeenCalledWith({ status: "Pending" });
});
it("keeps Pending when picked on a dated draft", () => {
const onPatch = vi.fn();
render(
<WizardStepVendorTime
draft={{
...EMPTY_WIZARD_DRAFT,
type: "PM",
status: "Scheduled",
scheduledOn: "2026-06-01",
scheduleWeekOnly: false,
}}
vendors={[]}
onUpdate={vi.fn()}
onPatch={onPatch}
/>,
);
fireEvent.click(screen.getByRole("button", { name: /scheduled/i }));
fireEvent.click(screen.getByRole("button", { name: /^pending$/i }));
expect(onPatch).toHaveBeenCalledWith({ status: "Pending" });
});
});

View file

@ -11,6 +11,7 @@ import {
hasConcreteScheduleDate,
maybeAutoSchedulePatch,
mergeAutoSchedulePatch,
withAutoScheduleStatus,
} from "@/domain/work-orders/utils/wo-lifecycle-transitions";
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
@ -103,6 +104,33 @@ describe("wo-lifecycle-transitions", () => {
expect(mergeAutoSchedulePatch(row, { vendorId: "9" })).toEqual({ vendorId: "9" });
});
it("keeps an explicit wizard status pick on a dated draft", () => {
const draft = {
status: "Scheduled",
scheduledOn: "2026-06-01",
scheduleWeekOnly: false,
};
expect(withAutoScheduleStatus(draft, { status: "Pending" })).toEqual({ status: "Pending" });
expect(withAutoScheduleStatus(draft, { status: "Incomplete" })).toEqual({
status: "Incomplete",
});
});
it("still derives Scheduled when a concrete date is set on a draft", () => {
const draft = {
status: "Pending",
scheduledOn: "",
scheduleWeekOnly: false,
};
expect(
withAutoScheduleStatus(draft, { scheduledOn: "2026-06-02", scheduleWeekOnly: false }),
).toEqual({
scheduledOn: "2026-06-02",
scheduleWeekOnly: false,
status: "Scheduled",
});
});
it("keeps explicit status picks on dated rows", () => {
const row = {
status: "Scheduled",