mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-01 10:53:11 +00:00
fix(work-orders): require company not technician for Completed (SH-183)
This commit is contained in:
parent
aaba7ca2ea
commit
37a6098ecb
3 changed files with 58 additions and 11 deletions
|
|
@ -4,13 +4,13 @@ import type {
|
|||
} from "@/domain/work-orders/types/work-order-table-row";
|
||||
import type { WOType, WorkOrderWizardDraft } from "@/domain/work-orders/types/work-order-wizard";
|
||||
|
||||
/** Fields required to evaluate whether a WO may be marked Completed (SH-114 ∪ pending uplift). */
|
||||
/** Fields required to evaluate whether a WO may be marked Completed (SH-183 ∪ pending uplift). */
|
||||
export type WoClosabilityInput = {
|
||||
dispatcherId: string;
|
||||
dispatcherName: string;
|
||||
/** Vendor/company assignment on the board row. */
|
||||
/** Company / vendor assignment — required for Completed (SH-183). */
|
||||
company: string;
|
||||
/** Technician assigned to the work order. */
|
||||
/** Technician is optional for closability; modeled separately from company. */
|
||||
tech: string;
|
||||
/** Work completed date (API CompletedDate). Empty until set. */
|
||||
completedDate: string;
|
||||
|
|
@ -51,6 +51,10 @@ function hasDispatcher(row: Pick<WoClosabilityInput, "dispatcherId" | "dispatche
|
|||
return Boolean(row.dispatcherId.trim() || row.dispatcherName.trim());
|
||||
}
|
||||
|
||||
function hasCompany(company: string): boolean {
|
||||
return Boolean(company.trim());
|
||||
}
|
||||
|
||||
function hasService(pm: string): boolean {
|
||||
return Boolean(pm.trim());
|
||||
}
|
||||
|
|
@ -70,8 +74,8 @@ export function getClosabilityGaps(row: WoClosabilityInput): string[] {
|
|||
if (!hasDispatcher(row)) {
|
||||
gaps.push("Dispatcher");
|
||||
}
|
||||
if (!row.tech.trim()) {
|
||||
gaps.push("Technician");
|
||||
if (!hasCompany(row.company)) {
|
||||
gaps.push("Company");
|
||||
}
|
||||
if (!row.completedDate.trim()) {
|
||||
gaps.push("Completed Date");
|
||||
|
|
@ -133,7 +137,7 @@ export function wizardDraftToClosabilityInput(draft: WorkOrderWizardDraft): WoCl
|
|||
dispatcherId: draft.assigneeId,
|
||||
dispatcherName: draft.assigneeName,
|
||||
company: draft.vendorName,
|
||||
tech: draft.vendorName,
|
||||
tech: "",
|
||||
completedDate: "",
|
||||
woNumber: draft.woNumber,
|
||||
pm: draft.pm,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ function makeRow(overrides: Partial<WorkOrderTableRow> = {}): WorkOrderTableRow
|
|||
woNumber: "1001",
|
||||
site: "BK5",
|
||||
type: "PM",
|
||||
severity: null,
|
||||
dispatcherId: "u1",
|
||||
dispatcherName: "Alex",
|
||||
scheduledOn: "2026-07-15",
|
||||
|
|
@ -116,4 +117,43 @@ describe("StatusCell pending uplift closability", () => {
|
|||
|
||||
expect(onChangeStatus).toHaveBeenCalledWith("Completed");
|
||||
});
|
||||
|
||||
it("disables Completed when company is missing (SH-183)", () => {
|
||||
const onChangeStatus = vi.fn();
|
||||
|
||||
renderWithProviders(
|
||||
<StatusCell
|
||||
wo={makeRow({ company: "" })}
|
||||
onChangeStatus={onChangeStatus}
|
||||
onOpenSlideOver={vi.fn()}
|
||||
/>,
|
||||
{ withAuth: false },
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /in progress/i }));
|
||||
|
||||
const completed = screen.getByRole("button", { name: /completed/i });
|
||||
expect(completed).toBeDisabled();
|
||||
expect(completed).toHaveAttribute("title", "Missing: Company");
|
||||
fireEvent.click(completed);
|
||||
expect(onChangeStatus).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows Completed when technician is empty if company is set (SH-183)", () => {
|
||||
const onChangeStatus = vi.fn();
|
||||
|
||||
renderWithProviders(
|
||||
<StatusCell
|
||||
wo={makeRow({ tech: "" })}
|
||||
onChangeStatus={onChangeStatus}
|
||||
onOpenSlideOver={vi.fn()}
|
||||
/>,
|
||||
{ withAuth: false },
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /in progress/i }));
|
||||
fireEvent.click(screen.getByRole("button", { name: /completed/i }));
|
||||
|
||||
expect(onChangeStatus).toHaveBeenCalledWith("Completed");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -60,12 +60,15 @@ describe("getClosabilityGaps", () => {
|
|||
expect(getClosabilityGaps(makeInput())).toEqual([]);
|
||||
});
|
||||
|
||||
it("blocks Completed when technician is missing", () => {
|
||||
expect(getClosabilityGaps(makeInput({ tech: "" }))).toEqual(["Technician"]);
|
||||
it("allows company without technician (SH-183)", () => {
|
||||
const gaps = getClosabilityGaps(makeInput({ tech: "" }));
|
||||
expect(gaps).toEqual([]);
|
||||
expect(gaps).not.toContain("Technician");
|
||||
});
|
||||
|
||||
it("does not block Completed when vendor/company is empty if technician is assigned", () => {
|
||||
expect(getClosabilityGaps(makeInput({ company: "" }))).toEqual([]);
|
||||
it("blocks Completed when company is missing even if technician is assigned", () => {
|
||||
expect(getClosabilityGaps(makeInput({ company: "", tech: "Sam" }))).toEqual(["Company"]);
|
||||
expect(getClosabilityGaps(makeInput({ company: " ", tech: "Sam" }))).toEqual(["Company"]);
|
||||
});
|
||||
|
||||
it("lists field gaps before uplift and document gaps", () => {
|
||||
|
|
@ -86,7 +89,7 @@ describe("getClosabilityGaps", () => {
|
|||
),
|
||||
).toEqual([
|
||||
"Dispatcher",
|
||||
"Technician",
|
||||
"Company",
|
||||
"Completed Date",
|
||||
"WO number",
|
||||
"Service",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue