Skip to content

Notifications

RateNet dispatches transactional emails to every party involved in a booking or billing event. The notification system is event-driven and multi-recipient: a single lifecycle event (e.g. booking confirmed) can send different, contextually appropriate emails to the guest, the client agency, the hotel, the tenant operator, and a system-level superadmin mailbox — all from one trigger.


Architecture overview

Domain event (e.g. booking confirmed)
  BookingNotifier / StatementNotifier
        ├─ resolveRecipients()  ← who gets notified for this event?
        ├─ subject()            ← per-recipient subject line
        ├─ templateName()       ← {event}_{recipientType}
        └─ EmailService.SendTemplated()  ← async SMTP dispatch

Notifications are fire-and-forget: they are sent asynchronously and never block the booking or billing flow. Errors are logged but not propagated.


Recipient types

Type Constant Who they are
holder RecipientHolder The guest/traveller who made the booking
client RecipientClient The client agency's back-office (confirmation email)
hotel RecipientHotel The hotel property contact
tenant RecipientTenant The platform operator running the tenant instance
superadmin RecipientSuperadmin System-level inbox — sees full cross-party context including sell price, cost, and margin

3-tier email routing

Every party has a master email (required fallback) and optional domain-specific overrides that let you route different notification types to different inboxes.

System level (.env)

This is the superadmin inbox. It receives a copy of every event with full financial context (tenant, client, hotel, sell, cost, margin). It is deliberately not stored in the database.

Tenant level

Field Domain Description
notification_email Master fallback Required. Used when no domain-specific email is set.
reservations_email reservations Overrides master for booking lifecycle events
finance_email finance Overrides master for invoice and statement events
account_management_email account_management Reserved for account management notifications
cc_admins_on_notifications Whether platform admins are CC'd (currently informational)

Client level

Field Domain Description
confirmation_email Master fallback The client's main notification address
reservations_email reservations Overrides for booking confirmations/cancellations
finance_email finance Overrides for statements sent to the client

Hotel level (direct contracts)

Field Domain Description
hotel_email Master fallback The hotel's main contact email
reservations_email reservations Overrides for booking notification to the hotel
finance_email finance Overrides for AP statement notifications

The EmailForDomain(domain string) string method is implemented on Tenant, Client, and SupplierHotel. It returns the domain-specific email if set, falling back to the master email.


Booking events

Booked through BookingNotifier, triggered by bookingService.NotifyAllParties().

Event Constant Recipient matrix
Booking Confirmed EventBookingConfirmed holder, client, hotel, tenant, superadmin
Booking Cancelled EventBookingCancelled holder, client, hotel, tenant, superadmin
Booking Amended EventBookingAmended holder, client, hotel, tenant, superadmin
Hotel Confirmed by Hotel EventHotelConfirmedByHotel holder, client, hotel, tenant, superadmin
Booking Invoiced EventBookingInvoiced tenant, superadmin only (internal financial event)
Deadline Reminder EventDeadlineReminder holder, client, tenant, superadmin (hotel excluded)

Subject line patterns

Recipient Example
Holder Booking Confirmed - RN-00123
Client New Booking Confirmation - RN-00123 - Grand Hotel
Hotel New Booking - RN-00123 - Grand Hotel
Tenant [Booking Confirmed] RN-00123 - Grand Hotel
Superadmin [System] Booking Confirmed - RN-00123 - Grand Hotel - 1250.00 EUR

Template naming

Template names follow the pattern {event}_{recipientType}:

booking_confirmed_holder
booking_confirmed_client
booking_confirmed_hotel
booking_confirmed_tenant
booking_confirmed_superadmin
booking_cancelled_holder
booking_cancelled_client
...
deadline_reminder_holder
deadline_reminder_client
deadline_reminder_tenant
deadline_reminder_superadmin

Template data

All booking templates receive a notificationTemplateData struct with:

Field Description
BookingRef Booking reference number
HolderName Guest full name
HotelName Hotel property name
DestinationName / Country Location fields
Checkin / Checkout Dates formatted as YYYY-MM-DD
BoardName Board type (e.g. Bed & Breakfast)
Rooms Number of rooms
FinalTotal / FinalCost / Margin Financial figures — all available in every template
Currency ISO currency code
Deadline Cancellation deadline (or N/A)
FreeCancellation Boolean — true if deadline is in the future
DaysToDeadline Days until deadline
TenantName / ClientName Party names
HotelPortalURL Deep link to hotel portal (hotel templates)
HotelConfirmationCode Hotel's own reference number
ChangeType Human-readable: New Booking, Cancellation, Amendment, etc.

Statement events

Handled by StatementNotifier, triggered by statementService.Notify().

Event Constant Recipient matrix
Statement Created EventStatementCreated tenant, superadmin
Statement Sent EventStatementSent tenant, client (AR only), superadmin
Statement Paid EventStatementPaid tenant, superadmin
Statement Voided EventStatementVoided tenant, superadmin

AR = Accounts Receivable (client owes money). AP = Accounts Payable (we owe the hotel/supplier).

Subject line patterns

Recipient Example
Tenant [AR] Statement Created - SOA-202603-001 - Woltravel Agency
Client (statement sent) Statement of Account - SOA-202603-001 - 12500.00 EUR
Superadmin [System][AR] Statement Created - SOA-202603-001 - Woltravel Agency

Template naming

statement_created_tenant
statement_created_superadmin
statement_sent_tenant
statement_sent_client
statement_sent_superadmin
statement_paid_tenant
statement_paid_superadmin
statement_voided_tenant
statement_voided_superadmin

Deadline reminders

Deadline reminders run as a background task on a configurable schedule per tenant.

Tenant configuration:

Setting Default Description
deadline_reminder_enabled false Enables the reminder background task for this tenant
deadline_reminder_days 7,3,1 Comma-separated list of days-before-deadline to trigger reminders

The DeadlineReminder service queries for confirmed, non-nonrefundable bookings whose deadline falls within a ±12-hour window of each configured tier. Reminders are guaranteed idempotent — each (booking_id, tier_days) pair is recorded in deadline_reminder_sents and will never be sent twice.


Email service

EmailService handles SMTP dispatch with an in-memory audit log.

Configuration (.env):

SMTP_HOST=smtp.example.com
SMTP_PORT=587
[email protected]
SMTP_PASSWORD=secret
[email protected]
SMTP_FROM_NAME=RateNet

Key behaviours:

  • Sending is always asynchronous (goroutine per email)
  • 30-second timeout per send attempt
  • In-memory audit log (last 10,000 records) accessible via emailService.GetAuditLog()
  • Failed emails accessible via emailService.GetFailedEmails()
  • If SMTP_HOST is not set, SendTemplated() returns an error immediately (no panic)

Adding a new event

  1. Define a new constant in booking_notifier.go or statement_notifier.go
  2. Add recipient logic in resolveRecipients()
  3. Add subject lines in subject()
  4. Add template(s) in email.go following the {event}_{recipientType} naming convention
  5. Call NotifyBookingEvent() or NotifyStatementEvent() from the service layer