import type { WorkOrderAuditEntry } from "@/domain/work-orders/types/work-order-detail"; export type AuditActionSource = Pick< WorkOrderAuditEntry, "action" | "fieldName" | "oldValue" | "newValue" >; export type FormattedAuditValue = { text: string; /** Per-item quotes already applied; omit outer quotes in sentence templates. */ isQuotedList: boolean; }; export function wrapAuditValue(value: FormattedAuditValue): string { if (!value.text) return value.text; return value.isQuotedList ? value.text : `"${value.text}"`; } export type AuditActionRuleContext = { entry: AuditActionSource; fieldKey: string; actionKey: string; oldValue: FormattedAuditValue; newValue: FormattedAuditValue; }; export type AuditActionRule = (ctx: AuditActionRuleContext) => string | null; function tryStatusRule({ fieldKey, actionKey, newValue }: AuditActionRuleContext): string | null { const matches = fieldKey.includes("status") || fieldKey === "lifecyclestatus" || actionKey.includes("status"); if (!matches || !newValue.text) return null; return `Changed status to ${wrapAuditValue(newValue)}`; } function tryApptRule({ fieldKey, actionKey, oldValue, newValue, }: AuditActionRuleContext): string | null { const matches = fieldKey.includes("appt") || fieldKey.includes("appointment") || actionKey.includes("appt"); if (!matches) return null; if (oldValue.text && newValue.text) { return `Changed appt time from ${wrapAuditValue(oldValue)} to ${wrapAuditValue(newValue)}`; } if (newValue.text) return `Changed appt time to ${wrapAuditValue(newValue)}`; return null; } function tryScheduleRule({ fieldKey, actionKey, newValue }: AuditActionRuleContext): string | null { const matches = fieldKey.includes("scheduled") || fieldKey === "schedule" || fieldKey.includes("scheduledate") || fieldKey.includes("duedate") || actionKey === "rescheduled" || actionKey.includes("reschedule"); if (!matches) return null; if (newValue.text) return `Changed schedule to ${wrapAuditValue(newValue)}`; return "Rescheduled work order"; } function tryCarriedOverRule({ fieldKey, actionKey, entry }: AuditActionRuleContext): string | null { const matches = fieldKey.includes("carriedover") || actionKey === "weekrolled" || actionKey.includes("carryover"); if (!matches) return null; const increment = Number(entry.newValue?.trim() ?? ""); if (Number.isFinite(increment) && increment > 0) { return `Carried over to the next week (increment #${increment})`; } return "Carried over to the next week"; } function tryPastDueRule({ fieldKey, actionKey }: AuditActionRuleContext): string | null { const matches = fieldKey.includes("pastdue") || actionKey.includes("pastdue") || actionKey === "markedpastdue"; if (!matches) return null; return "WO marked as Past Due. Due date has passed without completion."; } function tryCreatedRule({ fieldKey, actionKey }: AuditActionRuleContext): string | null { const matches = fieldKey === "created" || actionKey === "workordercreated" || actionKey === "created"; if (!matches) return null; return "Work order created in the system."; } /** Applied in order; the first non-null result wins. */ export const BOARD_AUDIT_ACTION_RULES: AuditActionRule[] = [ tryStatusRule, tryApptRule, tryScheduleRule, tryCarriedOverRule, tryPastDueRule, tryCreatedRule, ];