mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-02 05:03:12 +00:00
fix(work-orders): fail closed on unknown uplift status
This commit is contained in:
parent
ccfb3d9e6d
commit
a3e9a20477
3 changed files with 37 additions and 8 deletions
|
|
@ -25,6 +25,7 @@ function rowClosabilityGaps(wo: WorkOrderTableRow) {
|
|||
return getClosabilityGaps({
|
||||
dispatcherId: wo.dispatcherId,
|
||||
dispatcherName: wo.dispatcherName,
|
||||
company: wo.company,
|
||||
tech: wo.tech,
|
||||
completedDate: wo.completedDate ?? "",
|
||||
woNumber: wo.woNumber,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ import type { WOType, WorkOrderWizardDraft } from "@/domain/work-orders/types/wo
|
|||
export type WoClosabilityInput = {
|
||||
dispatcherId: string;
|
||||
dispatcherName: string;
|
||||
/** Vendor / technician assignment on the board row. */
|
||||
/** Vendor/company assignment on the board row. */
|
||||
company: string;
|
||||
/** Technician name is informational and does not satisfy the vendor requirement. */
|
||||
tech: string;
|
||||
/** Work completed date (API CompletedDate). Empty until set. */
|
||||
completedDate: string;
|
||||
|
|
@ -22,6 +24,7 @@ export type WoClosabilityInput = {
|
|||
};
|
||||
|
||||
export const PENDING_UPLIFT_GAP = "Pending uplift approval";
|
||||
export const UPLIFT_STATUS_UNAVAILABLE_GAP = "Uplift status unavailable";
|
||||
|
||||
/** Design copy when Completed is blocked solely by a pending uplift. */
|
||||
export const UPLIFT_PENDING_COMPLETED_TITLE =
|
||||
|
|
@ -45,6 +48,12 @@ export function hasPendingUplift(
|
|||
return (row.upliftSummary?.pendingCount ?? 0) > 0;
|
||||
}
|
||||
|
||||
function hasKnownUpliftStatus(
|
||||
row: Pick<WoClosabilityInput, "upliftSummary" | "hasPendingUplift">,
|
||||
): boolean {
|
||||
return typeof row.hasPendingUplift === "boolean" || row.upliftSummary != null;
|
||||
}
|
||||
|
||||
function hasDispatcher(row: Pick<WoClosabilityInput, "dispatcherId" | "dispatcherName">): boolean {
|
||||
return Boolean(row.dispatcherId.trim() || row.dispatcherName.trim());
|
||||
}
|
||||
|
|
@ -68,8 +77,8 @@ export function getClosabilityGaps(row: WoClosabilityInput): string[] {
|
|||
if (!hasDispatcher(row)) {
|
||||
gaps.push("Dispatcher");
|
||||
}
|
||||
if (!row.tech.trim()) {
|
||||
gaps.push("Technician");
|
||||
if (!row.company.trim()) {
|
||||
gaps.push("Company / vendor");
|
||||
}
|
||||
if (!row.completedDate.trim()) {
|
||||
gaps.push("Completed Date");
|
||||
|
|
@ -81,7 +90,9 @@ export function getClosabilityGaps(row: WoClosabilityInput): string[] {
|
|||
gaps.push("Service");
|
||||
}
|
||||
|
||||
if (hasPendingUplift(row)) {
|
||||
if (!hasKnownUpliftStatus(row)) {
|
||||
gaps.push(UPLIFT_STATUS_UNAVAILABLE_GAP);
|
||||
} else if (hasPendingUplift(row)) {
|
||||
gaps.push(PENDING_UPLIFT_GAP);
|
||||
}
|
||||
|
||||
|
|
@ -126,6 +137,7 @@ export function wizardDraftToClosabilityInput(draft: WorkOrderWizardDraft): WoCl
|
|||
return {
|
||||
dispatcherId: draft.assigneeId,
|
||||
dispatcherName: draft.assigneeName,
|
||||
company: draft.vendorName,
|
||||
tech: draft.vendorName,
|
||||
completedDate: "",
|
||||
woNumber: draft.woNumber,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
|
|||
import type { WoClosabilityInput } from "@/domain/work-orders/utils/wo-closability";
|
||||
import {
|
||||
PENDING_UPLIFT_GAP,
|
||||
UPLIFT_STATUS_UNAVAILABLE_GAP,
|
||||
UPLIFT_PENDING_COMPLETED_TITLE,
|
||||
canGenerateCompDoc,
|
||||
formatClosabilityMissingTitle,
|
||||
|
|
@ -14,6 +15,7 @@ function makeInput(overrides: Partial<WoClosabilityInput> = {}): WoClosabilityIn
|
|||
return {
|
||||
dispatcherId: "u1",
|
||||
dispatcherName: "Alex",
|
||||
company: "Acme HVAC",
|
||||
tech: "Sam",
|
||||
completedDate: "2026-07-01",
|
||||
woNumber: "1001",
|
||||
|
|
@ -21,8 +23,7 @@ function makeInput(overrides: Partial<WoClosabilityInput> = {}): WoClosabilityIn
|
|||
docStatus: "Yes",
|
||||
mediaCount: 1,
|
||||
type: "PM",
|
||||
upliftSummary: undefined,
|
||||
hasPendingUplift: undefined,
|
||||
hasPendingUplift: false,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
|
@ -47,7 +48,7 @@ describe("hasPendingUplift", () => {
|
|||
).toBe(true);
|
||||
});
|
||||
|
||||
it("is false when no uplift signals are present", () => {
|
||||
it("is false when uplift is explicitly not pending", () => {
|
||||
expect(hasPendingUplift(makeInput())).toBe(false);
|
||||
expect(
|
||||
hasPendingUplift(makeInput({ upliftSummary: { hasUplift: false, pendingCount: 0 } })),
|
||||
|
|
@ -60,12 +61,21 @@ describe("getClosabilityGaps", () => {
|
|||
expect(getClosabilityGaps(makeInput())).toEqual([]);
|
||||
});
|
||||
|
||||
it("accepts a company without a technician", () => {
|
||||
expect(getClosabilityGaps(makeInput({ tech: "" }))).toEqual([]);
|
||||
});
|
||||
|
||||
it("does not let a technician satisfy a missing company requirement", () => {
|
||||
expect(getClosabilityGaps(makeInput({ company: "" }))).toEqual(["Company / vendor"]);
|
||||
});
|
||||
|
||||
it("lists field gaps before uplift and document gaps", () => {
|
||||
expect(
|
||||
getClosabilityGaps(
|
||||
makeInput({
|
||||
dispatcherId: "",
|
||||
dispatcherName: "",
|
||||
company: " ",
|
||||
tech: " ",
|
||||
completedDate: "",
|
||||
woNumber: "SH-1",
|
||||
|
|
@ -77,7 +87,7 @@ describe("getClosabilityGaps", () => {
|
|||
),
|
||||
).toEqual([
|
||||
"Dispatcher",
|
||||
"Technician",
|
||||
"Company / vendor",
|
||||
"Completed Date",
|
||||
"WO number",
|
||||
"Service",
|
||||
|
|
@ -96,6 +106,12 @@ describe("getClosabilityGaps", () => {
|
|||
expect(getClosabilityGaps(makeInput({ hasPendingUplift: true }))).toEqual([PENDING_UPLIFT_GAP]);
|
||||
});
|
||||
|
||||
it("blocks Completed when the backend does not provide uplift status", () => {
|
||||
expect(
|
||||
getClosabilityGaps(makeInput({ hasPendingUplift: undefined, upliftSummary: undefined })),
|
||||
).toEqual([UPLIFT_STATUS_UNAVAILABLE_GAP]);
|
||||
});
|
||||
|
||||
it("requires a photo for Emergency / Reactive", () => {
|
||||
expect(
|
||||
getClosabilityGaps(makeInput({ type: "Emergency", mediaCount: 0, docStatus: "No" })),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue