shoc-frontend-new/src/domain/work-orders/utils/read-detail-closability-fields.ts

100 lines
3.1 KiB
TypeScript

import {
DOC_STATUS_API,
WORK_ORDER_TYPE_API_TO_FE,
} from "@/domain/work-orders/types/work-order-board";
import type { CompletionDocStatus } from "@/domain/work-orders/types/work-order-table-row";
import type { WOType } from "@/domain/work-orders/types/work-order-wizard";
// SH-126/SH-184: Add-On is a backend-authoritative indicator (`isAddOn`), not a
// selectable business type, so it is no longer part of the WOType union.
const DETAIL_WO_TYPES = new Set(["PM", "Reactive", "Emergency", "Overdue"]);
function asRecord(raw: unknown): Record<string, unknown> {
return typeof raw === "object" && raw !== null ? (raw as Record<string, unknown>) : {};
}
function readString(record: Record<string, unknown>, ...keys: string[]): string {
for (const key of keys) {
const value = record[key];
if (typeof value === "string") {
return value;
}
if (typeof value === "number") {
return String(value);
}
}
return "";
}
function readNumber(record: Record<string, unknown>, ...keys: string[]): number | null {
for (const key of keys) {
const value = record[key];
if (typeof value === "number") {
return value;
}
if (typeof value === "string" && value !== "") {
const parsed = Number(value);
if (!Number.isNaN(parsed)) {
return parsed;
}
}
}
return null;
}
/** Authoritative WO type only — never falls back to integration `source`. */
export function readDetailWoType(record: Record<string, unknown>): WOType | "" {
const numeric =
readNumber(record, "workOrderType", "WorkOrderType") ?? readNumber(record, "type", "Type");
if (numeric != null && WORK_ORDER_TYPE_API_TO_FE[numeric]) {
return WORK_ORDER_TYPE_API_TO_FE[numeric] as WOType;
}
const raw = readString(
record,
"workOrderType",
"WorkOrderType",
"type",
"Type",
"woType",
"WoType",
);
if (DETAIL_WO_TYPES.has(raw)) {
return raw as WOType;
}
return "";
}
export function readDetailDocStatus(record: Record<string, unknown>): CompletionDocStatus {
const numeric = readNumber(record, "docStatus", "DocStatus");
if (numeric === DOC_STATUS_API.Yes) return "Yes";
if (numeric === DOC_STATUS_API.No) return "No";
if (numeric === DOC_STATUS_API.NotNeeded) return "NN";
const nestedCompletion = asRecord(record.completion ?? record.Completion);
const nestedNumeric = readNumber(nestedCompletion, "docStatus", "DocStatus");
if (nestedNumeric === DOC_STATUS_API.Yes) return "Yes";
if (nestedNumeric === DOC_STATUS_API.No) return "No";
if (nestedNumeric === DOC_STATUS_API.NotNeeded) return "NN";
const raw = readString(record, "docStatus", "DocStatus", "completionDoc", "CompletionDoc");
if (raw === "Yes" || raw === "No" || raw === "NN") {
return raw;
}
if (raw === "NotNeeded") {
return "NN";
}
return "";
}
export function readDetailMediaCount(record: Record<string, unknown>): number {
const explicit = readNumber(record, "mediaCount", "MediaCount");
if (explicit != null) {
return explicit;
}
const media = record.media ?? record.Media;
if (Array.isArray(media)) {
return media.length;
}
return 0;
}