Pre-arrival messages (T-14 / T-3 / T-1 / T-0)
Four phases keyed off the arrival date. Implemented in
src/workflows/pre-arrival-messages.ts. All gated by the
pre-arrival-messages feature flag (currently shadow_mode=0, live).
Each phase is exposed as a separate call (runPreArrivalSingle in
BookingFlagWorkflow) so it can be
interleaved with M4c (A-2), the arrival flag (A-1 evening), the Bill
arrival email (A+0), and the still-dirty check (A+0 3pm) in true
temporal order. The earlier bundled-loop design broke M4c and M4d.
The four phases
| Phase | Fires at | What | Conditional? |
|---|---|---|---|
| T-14 | A −14d 15:00Z | Welcome email + 3 form links + yellow flag “checkin info sent” | Always (if booking has email) |
| T-3 | A −3d 15:00Z | Pre-check-in reminder + pink flag “Pre-check-in late” | If not complete + ≥24h since last msg |
| T-1 | A −1d 15:00Z | Final pre-check-in reminder | If not complete + ≥24h since last msg |
| T-0 | A +0 14:00Z | Lock-box codes OR hard nudge | Always (bypasses 24h gate) |
A = arrival date. UTC. 15:00Z = 9am MT, 14:00Z = 8am MT.
BA calendar color progression
The flag color in BA’s calendar tracks pre-checkin status at a glance:
| When | Color | Text |
|---|---|---|
| T-14 sends | ffffaa yellow | ”checkin info sent” |
| T-3 sends (still incomplete) | ffaaff pink | ”Pre-check-in late” |
| Pre-checkin form bridge | ffff56 bright yellow | ”Pre-check-in done” |
| A−1 evening | ff56aa arrival pink | (set by arrival phase) |
| Checkout-eve | aaffd4 mint | ”check-out tomorrow” |
| Departure | aaffff cyan | (set by departure phase) |
T-5 was retired — its dedicated flag-only phase was dropped; the visual progression is now folded into T-14 (yellow) and T-3 (pink-late).
What each one sends
T-14 welcome
Subject: Welcome to {Property}! Your stay info
Body: friendly welcome + 3 forms (pre-check-in, check-in, check-out) +
booking summary (dates, guests) + early/late availability notes
(computed via getPrevBooking and computeTurnoverDays) + link to
property URL.
Also sets BA flag color ffffaa + text “checkin info sent” so the
booking shows yellow in BA’s calendar.
T-3 / T-1 reminders
Subject: Please complete your pre-check-in for {Property}
Body: tighter nudge with the pre-checkin URL. T-1 says “tomorrow” instead of “3 days”.
Skipped if CA_PRE_CHECKIN_COMPL=Y on the booking.
T-3 also sets BA flag color ffaaff + text “Pre-check-in late” when
it fires (i.e., when pre-checkin is still incomplete at A-3 days).
This overrides the yellow flag from T-14.
T-0 morning-of-arrival
Two branches depending on CA_PRE_CHECKIN_COMPL:
If complete → renders property_config.arrival_message_body (per-
unit content — see Property config)
wrapped in a greeting + check-in form link + signature. Template
supports {firstName} and {lockBoxCode} substitutions.
If incomplete → hard nudge: “We can’t release your lock box code until you complete the pre-check-in form. It takes 2 minutes.”
T-0 bypasses the 24h gate — most critical send of the sequence.
Channel routing
Per dispatchChannelFor:
- Direct / VRBO / unknown → email only (via Mailgun)
- Airbnb / Booking.com → both email (if real address) AND Beds24 thread message (routes to OTA chat)
24-hour gate
A new booking 3 days before arrival would otherwise blast all phases
back-to-back. The gate (in pre-arrival-messages.ts):
if (lastSent && Date.now() - Date.parse(lastSent) < MIN_GAP_MS) { return { skipped: true, reason: "within_24h_gate" };}last_pre_arrival_msg_at is updated after each send.
T-0 bypasses the gate — the morning-of arrival info is too important to skip.
Source
- Code:
src/workflows/pre-arrival-messages.ts - Tests:
test/workflows/pre-arrival-messages.test.ts(22 cases) - Feature flag:
feature_flags WHERE workflow_name='pre-arrival-messages'
BA AA mapping
| BA AA | Our phase |
|---|---|
| 286616 | T-14 (was T-7 in BA; bumped) |
| 288251 | Retired — visual flag folded into T-14 (yellow) + T-3 (pink-late) |
| 286885 | T-3 |
| 286773 | T-1 |
| 287537, 287540, 290167 (CC/SS/TP lock-box) | T-0 |
| 288261 (T-2 SMS) | skipped — was a no-op in BA |