fix(freight): guard booking-desk hours against overnight ranges

Review follow-ups on the window-close-hour feature:

- Reject windowCloseHour < windowOpenHour when saving global rules. The
  reopen engine (nextCycleOpensAt) assumes the daily desk runs within one
  EAT day; an overnight range would misroute a ready-time inside the span
  to the next morning. openHour === closeHour stays valid (24-hour desk).
- Derive the board projection's runaway cap from the real first-open →
  departure span over the minimum per-cycle advance, so a legitimate
  long-lead config is never silently truncated (was a flat 200).
- Document the open <= close precondition on nextCycleOpensAt and clarify
  the ready-before-open comment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marshal
2026-07-05 09:07:21 +00:00
parent 93b8b69464
commit dfdf7a025d
3 changed files with 31 additions and 8 deletions

View File

@@ -110,10 +110,11 @@ describe('batch-window board windows (config-driven booking cycles)', () => {
(w, i) => i > 0 && windows[i - 1].date !== w.date,
);
expect(crossesNight).toBe(true);
// Cycles run continuously from the window day up to departure.
expect(windows[windows.length - 1].end.getTime()).toBeLessThanOrEqual(
departure.getTime(),
);
// Cycles run continuously from the window day up to departure — the last one
// reaches departure, proving the runaway cap did not truncate the projection.
expect(windows[windows.length - 1].end.getTime()).toBe(departure.getTime());
// Spans the full lead (window day 05 Jun → departure 08 Jun).
expect(new Set(windows.map((w) => w.date)).size).toBeGreaterThanOrEqual(3);
});
it('export: single FCFS window exportBookingLeadHours before departure', () => {