import { addDaysIso, mondayOf } from "@/domain/work-orders/utils/wizard-date-utils"; const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/; /** * Saturday of the week prior to the scheduledOn week (ISO date only). * Cutoff instant is end of that day (23:59:59 local). * * SH-184: backend recalculates `isAddOn` whenever scheduling moves across weeks * or is cleared, and owns audit. This helper is only a create-time FE hint. */ export function getAddonCutoffIso(scheduledOn: string): string | null { const trimmed = scheduledOn.trim(); if (!ISO_DATE.test(trimmed)) { return null; } return addDaysIso(mondayOf(trimmed), -2); } /** * Preview whether Add-On would apply for a create-time schedule + createdAt. * Returns null when scheduledOn is missing — callers may use a manual override. * * Not a freeze: after create (and on every schedule patch/clear) the backend is * authoritative; FE must consume the returned `isAddOn` (SH-184). */ export function previewIsAddOnFromCutoff(input: { createdAt: Date | string | number; scheduledOn: string; }): boolean | null { const cutoffIso = getAddonCutoffIso(input.scheduledOn); if (!cutoffIso) { return null; } const createdAt = input.createdAt instanceof Date ? input.createdAt : new Date(input.createdAt); if (Number.isNaN(createdAt.getTime())) { return null; } const cutoff = new Date(`${cutoffIso}T23:59:59`); return createdAt.getTime() > cutoff.getTime(); } /** @deprecated Prefer `previewIsAddOnFromCutoff` — name implied a freeze (SH-126). */ export const computeIsAddOnAtCreation = previewIsAddOnFromCutoff; /** * Resolve create-payload `isAddOn` hint: cutoff preview when scheduled, else * manual override. Backend may recalculate immediately and on later schedule * patches/clears; FE must not treat this value as frozen (SH-184). */ export function resolveIsAddOnForCreate(input: { createdAt?: Date | string | number; scheduledOn: string; manualOverride?: boolean; }): boolean { const computed = previewIsAddOnFromCutoff({ createdAt: input.createdAt ?? new Date(), scheduledOn: input.scheduledOn, }); if (computed !== null) { return computed; } return Boolean(input.manualOverride); }