v1.5.0
A large feature release: multi-resource availability, staff scheduling & auto-provisioning, an availability-aware calendar, guest (account-less) bookings, and full admin-UI internationalization. The plugin's public API and config surface remain additive — with no new options set, behavior is unchanged — so this is a minor release. However, there are behavioral and database-migration notes existing deployments should review before upgrading.
⚠️ Breaking changes & migration notes
- Multi-resource conflict detection corrected (behavioral). Conflict detection previously counted only a reservation's top-level
resourceand ignored resources held initems[]. It now also countsitems.resource, and multi-resource bookings receive a top-level[startTime, endTime]span. Existing multi-resource deployments will start correctly rejecting bookings that previously slipped through as silent double-bookings. Single-resource deployments are unaffected. Reservation.customeris now optional. To support guest bookings, thecustomerrelationship is no longer required at the schema level — a reservation must have either acustomeror aguest. On Postgres thecustomercolumn becomes nullable.- Resource
ownercollection changed for separate users/customers setups. WithresourceOwnerModeand separateusers/customerscollections, theownerrelationship now points atresourceOwnerMode.ownerCollection ?? staffProvisioning.userCollection ?? slugs.customersinstead of alwayscustomers. If you relied on the previous (incorrect)customerstarget, setresourceOwnerMode.ownerCollection: 'customers'explicitly. Single-collection / customer-owned setups are unchanged. - Postgres migrations required for the new fields:
Service.requiredResources,Resource.resourceType,Schedule.exceptions.endDate/exceptions.type, the reservationguestgroup +cancellationToken, theitemsarray, and the now-nullablecustomer(plus theownerrelationship target change above). MongoDB needs no migration. resourceTypedefault. New Resources defaultresourceTypeto the first entry ofresourceTypes('staff'by default).
Added
- Multi-resource availability. A service can declare
requiredResources(e.g. a shared chair pool) that every booking of it occupies. Slot discovery (getAvailableSlots,/api/reserve/slots,/api/reserve/availability) intersects the schedules and capacity of all required resources, and bookings are auto-expanded intoitems[]so conflict detection blocks a booking when any required pool is full. Adds a descriptiveresourceTypefield to Resources. - Staff scheduling & auto-provisioning. Opt-in
staffProvisioning(requiresresourceOwnerMode) auto-creates owner-scoped Resources from staff-role users, assigning ownership securely by impersonating the new staff user (no ownership-bypass flag). Adds full-day-range typed time-off onSchedule.exceptions(endDate+type) and configurableresourceTypes/leaveTypesvocabularies.Resource.servicesis now optional so freshly provisioned staff resources can exist before services are assigned. - Availability-aware calendar & booking. The reservation
startTimefield is now a slot picker that only offers free times for the chosen service + staff. The admin calendar's week/day views shade off-shift, time-off, and fully-booked slots when a resource is selected, show capacity (n/quantity), render time-off bands, and support click-to-book. Adds a resource-lane horizontal-timeline day view and multi-resource event badges, backed by a new read-only/api/reserve/resource-availabilityendpoint and a pure, testedcomputeSlotStatesutility. - Guest (account-less) bookings. New
allowGuestBookingplugin option (defaultfalse) plus a per-service tri-state override (inherit/enabled/disabled). Reservations may carry inlineguestcontact details (name + email/phone) instead of acustomer. Guest bookings receive acancellationTokenexposed via theafterBookingCreatehook so the host can deliver an email link or SMS code;/api/reserve/cancelaccepts{ reservationId, token }for unauthenticated guests. The plugin performs no email/SMS delivery itself. - Internationalization. Every admin string is now translatable, with 11 new bundled locales — French (
fr), German (de), Spanish (es), Russian (ru), Polish (pl), Turkish (tr), Arabic (ar), Simplified Chinese (zh), Indonesian (id), Hindi (hi), and Persian/Farsi (fa) — each with full key parity with English. Translations merge into Payload'si18nconfig and host-provided translations take precedence. All locales except Hindi ship in Payload core and appear in the admin language switcher automatically;himust be registered as a custom language by the host.
Fixed
- Silent double-bookings in multi-resource deployments — conflict detection now counts
items.resource(see Breaking changes above). - Resource
ownerpointed at the wrong collection inresourceOwnerModewith separateusers/customerscollections — it was hardcoded tocustomers. Now relates toresourceOwnerMode.ownerCollection ?? staffProvisioning.userCollection ?? customers, and adds an optionalresourceOwnerMode.ownerCollectionto override explicitly. - Staff/admin detection in single-collection (
userCollection) deployments. When customers and staff share one auth collection, the previousreq.user.collection === slugs.customerscheck could never identify staff. A new role-aware check (collection first, thenresourceOwnerMode.adminRoles ∪ staffProvisioning.staffRoles) fixes creating non-default-status reservations (e.g.confirmed) as staff/admin, the customer-search endpoint returning 403 to staff, and cancellation permission for staff/admin. Customer search also now excludes privileged-role users from results in single-collection mode. Two-collection deployments are unaffected.