Booking reminder e-mails
How the reminder e-mails run, how to switch them on, and how to check them. Rules: COMM-010 … COMM-014. What they say: Booking e-mails and reminders.
How it runs
- 09:00 IST daily — the pg_cron job
alhuda-booking-reminders(30 3 * * *, UTC) runsSELECT public.booking_reminders_run(). It needs no secret: it only writes rows. - It picks the confirmed bookings (
APPROVED,PARTIALLY_CANCELLED) whose departure is ahead, decides which reminders fall due today, claims each inBookingReminderLog(one row per booking, kind and date) and queues the e-mail inCommunicationQueue(messageTypebooking_reminder,createdBysystem). - Every five minutes — the existing job
alhuda-communications-dispatchersends the queue through thecommunications-dispatcherand themailer(Communications). The mailer adds the booking block and drops a payment reminder whose balance was paid in the meantime; the row is then cancelled withSkipped: balance_paid.
Nothing is sent while Send reminder e-mails is off. It ships off.
Switching reminders on
Admin → Reminders (needs admin.integrations.edit):
- Check the days. Defaults:
| Setting | Default | Bounds |
|---|---|---|
| Payment due — days before the due date | 7 | 1–90 |
| Due date when the departure has none — days before departure | 30 | 0–365 |
| Overdue — repeat every | 7 days | 1–60 |
| Overdue — at most | 4 times | 1–20 |
| Departure — days before | 7, 1 | up to 5 values, 1–120 |
| Documents — days before | 45, 21 | up to 5 values, 1–180 |
A departure's own due date is balance due days before departure on the group. 2. Turn on Send reminder e-mails and press Save. The screen asks first. 3. The first reminders are queued at the next 09:00 IST run.
Before switching on, the owner should know that every confirmed booking with an open balance past its due date gets an overdue reminder at the first run. Check the balances in the booking list first if the payment records are behind.
Checking
- Admin → Reminders lists the last 50 reminders: booking, kind, the date it is for, customer or partner, and the result (Waiting to send, Sent, Failed, Not sent — opted out of e-mail, Not sent — no e-mail address, Not sent — no longer needed).
- The queue:
/communications→ scheduled queue (communications.send). - The job, in the SQL editor:
SELECT jobname, schedule, active FROM cron.job WHERE jobname = 'alhuda-booking-reminders';
SELECT status, return_message, start_time FROM cron.job_run_details
WHERE jobid = (SELECT jobid FROM cron.job WHERE jobname = 'alhuda-booking-reminders')
ORDER BY start_time DESC LIMIT 5;
By hand
A run for today (the service role, or the SQL editor):
It returns { enabled, today, queued, skipped, byKind }. A second run the same day queues
nothing more. To see what a given day would do, run it inside a transaction and roll back:
Stopping
- All reminders: turn off Send reminder e-mails. Rows already queued still go at the next
dispatcher run; to stop those too, cancel the pending
booking_reminderrows in the queue. - One kind: switch that kind off.
- One customer: record their e-mail opt-out (AUD-022); the next reminder is skipped and logged.
- The job itself (only if it misbehaves):
SELECT cron.unschedule('alhuda-booking-reminders');. Re-applying the migration schedules it again.
Deploy
The migration 20261003220100_booking_reminder_emails.sql creates the tables, the functions and
the job. The mailer and communications-dispatcher edge functions must be deployed with it (the
booking_reminder template and the skip handling live there). Where pg_cron is missing the
migration logs a notice and succeeds; run booking_reminders_run() by hand then.