Skip to content

Overview

Bookings provides a public appointment-request form and admin resources for services, staff, locations, availability, appointment workflow, message logs, lesson records, group sessions, reviews, waitlists, travel planning, and related operational records. The core public flow creates a Requested appointment; an operator then confirms or cancels it.

Run the package and settings migrations. Configure application mail and keep a queue worker running: confirmation, cancellation, and reminder emails are queued Laravel notifications. Keep Laravel’s scheduler running as well. The package schedules:

  • capell:bookings:send-due-reminders every five minutes;
  • capell:bookings:expire-workflow-state every five minutes for provisional holds, change proposals, and waitlist offers;
  • capell:bookings:schedule-review-requests hourly;
  • capell:bookings:prune-retention-data daily.

The runtime actions currently read values from capell-bookings.* deployment config, including hold expiry, reminder lead time, review offsets, message-log retention, and travel-observation retention. Keep that config aligned with your intended package settings; do not assume that saving similarly named values on the Bookings settings screen alone changes those actions.

The default BookingMessageChannel is a local adapter that records a synthetic provider ID but does not contact an email, SMS, or WhatsApp service. Bind a production message-channel implementation before using message logs, review messages, or other advanced channel workflows. Enabling the SMS, WhatsApp, AI, or Facebook toggles does not install or configure an external provider.

In Bookings, create active Services first. Duration, lead time, maximum future days, and before/after buffers are enforced when a request is created. Add active Staff and Locations, then create recurring Availability windows with the correct timezone and capacity. Use Availability exceptions for a blocked date or for extra date-specific capacity.

Requests must fit entirely inside an applicable window or available exception. Requested, Provisional, and Confirmed appointments consume capacity; service buffers also block adjoining time. Capacity checks run inside a transaction, but operators should still review unusual overlaps and timezone configuration before opening the form publicly.

The shipped /bookings form is installation-wide: it lists all active services, staff, and locations and does not derive a current frontend site. Requests submitted through that controller therefore have no site assignment. On a multisite installation, use a site-aware integration that calls the booking actions with an explicit site ID rather than assuming the default form provides site isolation.

Open Bookings > Appointment requests. Use the row’s Confirm and Cancel actions for the normal workflow: they validate the current state, write an audit event, and queue the corresponding customer email. Cancellation can store an operator reason. Editing the Status field directly does not run those workflow actions, so use direct status editing only for deliberate corrections such as marking a completed appointment or no-show.

The reminder scheduler queues one reminder for each Confirmed appointment entering the lead window (24 hours by default). It records Reminder queued immediately, so the scheduler will not create another reminder if the queued mail later fails. Monitor failed queue jobs and mail delivery; recover the failed job through your normal queue tooling rather than waiting for the next scheduler run.

For advanced messages, review Booking message logs. SMS and WhatsApp require recorded consent for the linked portal account; email is allowed without that channel-consent record. A failed message log exposes a confirmed Retry action and updates the same record with its new result and retry count.

A Provisional appointment blocks capacity until its hold expires (30 minutes by default). The five-minute workflow command changes expired holds to Cancelled. That bulk expiry does not create an appointment audit entry or queue a customer cancellation message.

Payment-gated confirmation is an integration point, not a complete checkout. Bookings can place a provisional hold and record a provider reference, checkout-session ID, amount, and payment-confirmed timestamp. It refuses to confirm a payment-policy appointment when the required amount has not been fulfilled, but this package does not create a checkout, interpret a recorded webhook, issue refunds, or automatically confirm the appointment. The payment integration must call the fulfilment action and then the confirmation action when its own verification succeeds.

Portal lesson and messaging-consent links are temporary signed URLs that expire after 14 days by default. Treat them as bearer links: anyone with a valid URL can see the linked shared lesson data or change channel consent until it expires.

A staff calendar feed URL is different: its 64-character token is stored in plaintext and has no built-in expiry. The feed contains Confirmed appointment times, service, customer name and notes, and location. Keep the URL private. The current staff screen has no rotate-feed action, and creating the URL again reuses the existing token, so an integrator must replace the stored token if it is disclosed.

The public webhook route requires both the configured provider token and an HMAC signature of the raw body. It deduplicates by provider/event ID and stores the payload as Received. Receiving or replaying that record does not process a payment or booking change; a separate integration must interpret it, perform the appropriate action, and mark it processed.

Each Bookings resource uses its generated Filament view/create/update/delete permissions. Global administrators bypass those permission checks. Record policies prevent a non-global administrator from viewing or changing records assigned to a site they do not manage, but the Filament resources do not apply a site-scoped base query. Records without a site ID are also treated as available to a permitted user. Grant Bookings view permissions only to roles allowed to see installation-wide table data; do not use those resources as a hard tenant boundary.

Appointment identity/contact details, notes, payloads, message recipients and bodies, consent evidence, lesson notes, travel observations, payment references, webhook payloads, and the staff calendar token are stored in plaintext. Review database, admin, queue, log, backup, calendar-client, and provider access accordingly.

When Privacy Center is available, Bookings contributes subject export and erasure. It resolves records through the portal account and matching email, omits internal IDs and token values from the export, and hard-deletes linked appointment, audit, lesson, message, consent, proposal, review, waitlist, skill, and bundle records during erasure. Review media files, external providers, calendars, queue payloads, backups, travel records, and webhook events separately; they are not all removed by that eraser.

The daily retention command only deletes old booking message logs and travel observations. Its deployment-config defaults are 730 and 365 days respectively. Appointment requests, audit logs, consent, notes, reviews, waitlists, payment references, webhook events, and calendar tokens have no general scheduled cleanup in this package.


For how to use Bookings, see the admin guide. For developers: see the README.