Skip to content

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

  1. 09:00 IST daily — the pg_cron job alhuda-booking-reminders (30 3 * * *, UTC) runs SELECT public.booking_reminders_run(). It needs no secret: it only writes rows.
  2. It picks the confirmed bookings (APPROVED, PARTIALLY_CANCELLED) whose departure is ahead, decides which reminders fall due today, claims each in BookingReminderLog (one row per booking, kind and date) and queues the e-mail in CommunicationQueue (messageType booking_reminder, createdBy system).
  3. Every five minutes — the existing job alhuda-communications-dispatcher sends the queue through the communications-dispatcher and the mailer (Communications). The mailer adds the booking block and drops a payment reminder whose balance was paid in the meantime; the row is then cancelled with Skipped: balance_paid.

Nothing is sent while Send reminder e-mails is off. It ships off.

Switching reminders on

Admin → Reminders (needs admin.integrations.edit):

  1. 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):

SELECT public.booking_reminders_run();

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:

BEGIN;
SELECT public.booking_reminders_run(DATE '2026-11-28');
ROLLBACK;

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_reminder rows 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.