mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 05:22:04 +00:00
fix(workorders): retain compatible inactive services
This commit is contained in:
parent
690820f0b9
commit
4a7da7cbd5
5 changed files with 99 additions and 14 deletions
|
|
@ -17,7 +17,7 @@ import type {
|
||||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||||
import type { WizardWOStatus } from "@/domain/work-orders/types/work-order-wizard";
|
import type { WizardWOStatus } from "@/domain/work-orders/types/work-order-wizard";
|
||||||
import type { Service } from "@/domain/services/types/service";
|
import type { Service } from "@/domain/services/types/service";
|
||||||
import { isServiceEligibleForWorkOrderType } from "@/domain/services/utils/services-for-work-order-type";
|
import { serviceSupportsWorkOrderType } from "@/domain/services/utils/services-for-work-order-type";
|
||||||
import { serviceIdentityPatch } from "@/domain/work-orders/utils/service-identity-patch";
|
import { serviceIdentityPatch } from "@/domain/work-orders/utils/service-identity-patch";
|
||||||
import { deriveDayFields } from "@/domain/work-orders/utils/table-day-utils";
|
import { deriveDayFields } from "@/domain/work-orders/utils/table-day-utils";
|
||||||
import { toVendorTablePatch } from "@/domain/work-orders/utils/vendor-assignment-patch";
|
import { toVendorTablePatch } from "@/domain/work-orders/utils/vendor-assignment-patch";
|
||||||
|
|
@ -180,7 +180,7 @@ export function SlideOverInfoTabEditView({
|
||||||
onDraftChange(
|
onDraftChange(
|
||||||
draft.serviceId != null &&
|
draft.serviceId != null &&
|
||||||
selectedService != null &&
|
selectedService != null &&
|
||||||
!isServiceEligibleForWorkOrderType(selectedService, type)
|
!serviceSupportsWorkOrderType(selectedService, type)
|
||||||
? { type, severity, serviceId: null, pm: "" }
|
? { type, severity, serviceId: null, pm: "" }
|
||||||
: { type, severity },
|
: { type, severity },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import type {
|
||||||
} from "@/domain/work-orders/types/work-order-table-row";
|
} from "@/domain/work-orders/types/work-order-table-row";
|
||||||
import type { WOType } from "@/domain/work-orders/types/work-order-wizard";
|
import type { WOType } from "@/domain/work-orders/types/work-order-wizard";
|
||||||
import type { Service } from "@/domain/services/types/service";
|
import type { Service } from "@/domain/services/types/service";
|
||||||
import { isServiceEligibleForWorkOrderType } from "@/domain/services/utils/services-for-work-order-type";
|
import { serviceSupportsWorkOrderType } from "@/domain/services/utils/services-for-work-order-type";
|
||||||
import {
|
import {
|
||||||
formatSeverityEscalationToast,
|
formatSeverityEscalationToast,
|
||||||
shouldAnnounceSeverityEscalation,
|
shouldAnnounceSeverityEscalation,
|
||||||
|
|
@ -31,7 +31,7 @@ export function saveExistingRowType(
|
||||||
const clearService =
|
const clearService =
|
||||||
row.serviceId != null &&
|
row.serviceId != null &&
|
||||||
selectedService != null &&
|
selectedService != null &&
|
||||||
!isServiceEligibleForWorkOrderType(selectedService, type);
|
!serviceSupportsWorkOrderType(selectedService, type);
|
||||||
const patch = clearService ? { type, severity, serviceId: null, pm: "" } : { type, severity };
|
const patch = clearService ? { type, severity, serviceId: null, pm: "" } : { type, severity };
|
||||||
if (!shouldAnnounceSeverityEscalation(row.severity, severity)) {
|
if (!shouldAnnounceSeverityEscalation(row.severity, severity)) {
|
||||||
onPatch(row.id, patch);
|
onPatch(row.id, patch);
|
||||||
|
|
|
||||||
|
|
@ -10,5 +10,10 @@ export function servicesForWorkOrderType(services: Service[], type: WOType | "")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isServiceEligibleForWorkOrderType(service: Service, type: WOType | ""): boolean {
|
export function isServiceEligibleForWorkOrderType(service: Service, type: WOType | ""): boolean {
|
||||||
return service.isActive && service.supportedWorkOrderTypes.includes(serviceWorkOrderType(type));
|
return service.isActive && serviceSupportsWorkOrderType(service, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether a service definition supports a WO type, regardless of active assignment status. */
|
||||||
|
export function serviceSupportsWorkOrderType(service: Service, type: WOType | ""): boolean {
|
||||||
|
return service.supportedWorkOrderTypes.includes(serviceWorkOrderType(type));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,16 +78,36 @@ describe("saveExistingRowType", () => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
saveExistingRowType(onPatch, { ...row, serviceId: 701 }, "Reactive", null, services);
|
saveExistingRowType(onPatch, { ...row, serviceId: 701 }, "Emergency", null, services);
|
||||||
|
|
||||||
expect(onPatch).toHaveBeenCalledWith(7, {
|
expect(onPatch).toHaveBeenCalledWith(7, {
|
||||||
type: "Reactive",
|
type: "Emergency",
|
||||||
severity: null,
|
severity: null,
|
||||||
serviceId: null,
|
serviceId: null,
|
||||||
pm: "",
|
pm: "",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("preserves a known inactive historical service that supports the new type", () => {
|
||||||
|
const onPatch = vi.fn();
|
||||||
|
const services: Service[] = [
|
||||||
|
{
|
||||||
|
id: 702,
|
||||||
|
name: "Retired Multi-type Service",
|
||||||
|
trade: "Electrical",
|
||||||
|
iconKey: "wrench",
|
||||||
|
requiresCompletionDocument: false,
|
||||||
|
completionDocTemplate: null,
|
||||||
|
isActive: false,
|
||||||
|
supportedWorkOrderTypes: ["PM", "Reactive"],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
saveExistingRowType(onPatch, { ...row, serviceId: 702 }, "Reactive", null, services);
|
||||||
|
|
||||||
|
expect(onPatch).toHaveBeenCalledWith(7, { type: "Reactive", severity: null });
|
||||||
|
});
|
||||||
|
|
||||||
it("clears a known inactive historical service before type change", () => {
|
it("clears a known inactive historical service before type change", () => {
|
||||||
const onPatch = vi.fn();
|
const onPatch = vi.fn();
|
||||||
const services: Service[] = [
|
const services: Service[] = [
|
||||||
|
|
@ -103,10 +123,10 @@ describe("saveExistingRowType", () => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
saveExistingRowType(onPatch, { ...row, serviceId: 701 }, "Reactive", null, services);
|
saveExistingRowType(onPatch, { ...row, serviceId: 701 }, "Emergency", null, services);
|
||||||
|
|
||||||
expect(onPatch).toHaveBeenCalledWith(7, {
|
expect(onPatch).toHaveBeenCalledWith(7, {
|
||||||
type: "Reactive",
|
type: "Emergency",
|
||||||
severity: null,
|
severity: null,
|
||||||
serviceId: null,
|
serviceId: null,
|
||||||
pm: "",
|
pm: "",
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,19 @@ vi.mock(
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/type-cell", () => ({
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/type-cell", () => ({
|
||||||
TypeCell: ({ onSave }: { onSave: (type: "Reactive", severity: number) => void }) => (
|
TypeCell: ({
|
||||||
<button type="button" onClick={() => onSave("Reactive", 2)}>
|
onSave,
|
||||||
Change type to Reactive
|
}: {
|
||||||
</button>
|
onSave: (type: "Reactive" | "Emergency", severity: number) => void;
|
||||||
|
}) => (
|
||||||
|
<>
|
||||||
|
<button type="button" onClick={() => onSave("Reactive", 2)}>
|
||||||
|
Change type to Reactive
|
||||||
|
</button>
|
||||||
|
<button type="button" onClick={() => onSave("Emergency", 2)}>
|
||||||
|
Change type to Emergency
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/assigned-to-cell", () => ({
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/assigned-to-cell", () => ({
|
||||||
|
|
@ -227,12 +236,63 @@ describe("SlideOverInfoTabEditView additional contacts", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderWithProviders(<SlideOverSaveHarness />, { withAuth: false });
|
renderWithProviders(<SlideOverSaveHarness />, { withAuth: false });
|
||||||
fireEvent.click(screen.getByRole("button", { name: "Change type to Reactive" }));
|
fireEvent.click(screen.getByRole("button", { name: "Change type to Emergency" }));
|
||||||
fireEvent.click(screen.getByRole("button", { name: "Save changes" }));
|
fireEvent.click(screen.getByRole("button", { name: "Save changes" }));
|
||||||
|
|
||||||
expect(onSave).toHaveBeenCalledWith([
|
expect(onSave).toHaveBeenCalledWith([
|
||||||
{ field: "severity", value: "2" },
|
{ field: "severity", value: "2" },
|
||||||
{ field: "serviceId", value: "" },
|
{ field: "serviceId", value: "" },
|
||||||
|
{ field: "workOrderType", value: "Emergency" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves a compatible inactive service during a slide-over type change", () => {
|
||||||
|
const baseline = baseRow({ type: "PM", pm: "Historical service", serviceId: 702 });
|
||||||
|
const onSave = vi.fn();
|
||||||
|
const compatibleInactiveService = {
|
||||||
|
id: 702,
|
||||||
|
name: "Historical service",
|
||||||
|
trade: "Electrical",
|
||||||
|
iconKey: "wrench",
|
||||||
|
requiresCompletionDocument: false,
|
||||||
|
completionDocTemplate: null,
|
||||||
|
isActive: false,
|
||||||
|
supportedWorkOrderTypes: ["PM" as const, "Reactive" as const],
|
||||||
|
};
|
||||||
|
|
||||||
|
function SlideOverSaveHarness() {
|
||||||
|
const [draft, setDraft] = useState(baseline);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SlideOverInfoTabEditView
|
||||||
|
draft={draft}
|
||||||
|
users={[]}
|
||||||
|
sites={[]}
|
||||||
|
vendors={[]}
|
||||||
|
pmTypes={[]}
|
||||||
|
services={[]}
|
||||||
|
serviceHistory={[compatibleInactiveService]}
|
||||||
|
allOrders={[]}
|
||||||
|
onDraftChange={(patch) => setDraft((current) => ({ ...current, ...patch }))}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() =>
|
||||||
|
onSave(expandTablePatchToBoardFieldOps(buildSlideOverPatch(draft, baseline)))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Save changes
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderWithProviders(<SlideOverSaveHarness />, { withAuth: false });
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "Change type to Reactive" }));
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "Save changes" }));
|
||||||
|
|
||||||
|
expect(onSave).toHaveBeenCalledWith([
|
||||||
|
{ field: "severity", value: "2" },
|
||||||
{ field: "workOrderType", value: "Reactive" },
|
{ field: "workOrderType", value: "Reactive" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue