Developer notes
File map
Section titled “File map”app/addons/kv_booking_reservations/ addon.xml, init.php, func.php hooks, install, settings info handlers controllers/backend/kv_booking_reservations.php calendar, list, booking page, create, resources, export, cron controllers/backend/products.post.php "Booking" tab of the product editor controllers/frontend/kv_booking_reservations.php availability/slots/quote (JSON), my_bookings, cancel, ics, cron resources/email_templates.xml reminder, cancelled, cancellation request (Twig) schemas/ menu, permissions (admin, vendor), block cache, CSRF, setting variants Tygh/Addons/KvBookingReservations/ Config, Clock, Product, Blackouts, Resources, Engine, Pricing, Request, Reservation, Cart, OrderSync, Bookings, Presenter, Calendar, Exporter, Customer, Storefront, Ics, Mail, Reminders, License/, Upgrade/Synchronizerdesign/backend/templates/addons/kv_booking_reservations/ admin views, product tab, settings infosvar/themes_repository/responsive/templates/addons/kv_booking_reservations/ picker, cart lines, My bookingsjs/addons/kv_booking_reservations/func.js, backend.jsTables
Section titled “Tables”| Table | Contents |
|---|---|
kv_br_products |
Booking settings per product (mode, duration, buffer, capacity, weekly schedule as JSON, lead time, horizon, range unit, lengths, check-in/out weekday masks, persons, resources) |
kv_br_rules |
Price rules (date range, weekday mask, type A/P/F, value, position) |
kv_br_blackouts |
Exceptions of products (owner_type P) and resources (R): closed, special hours, capacity |
kv_br_resources, kv_br_product_resources |
Resources and their products |
kv_br_bookings |
Bookings: kind (O order, M manual, B block), status (H cart hold, P being placed, A active, X released), token of the cart line, order/item, start/end timestamps, local dates (day_to exclusive), units, guests, price, customer snapshot, expiry, reminder, cancellation data |
kv_br_locks |
One row per product or resource, locked while capacity is taken |
kv_br_meta |
Run marks of the reminder run |
All tables are InnoDB.
Availability
Section titled “Availability”A booking counts when its status is H, P or A and it has not expired. Time slots overlap when [start, end + break) of both intersect; with resources, the usage is counted per resource across all products that use it. Date ranges count per local date. Local wall-clock times are converted with DateTimeImmutable in the store time zone; times that do not exist (daylight saving gap) are skipped. SQL never does date math (CS-Cart sets a fixed UTC offset on the database session).
Reservation and locking
Section titled “Reservation and locking”Every write that takes capacity (cart hold, order placement, re-activation, manual booking, move) goes through Reservation::reserve(): the lock rows are created beforehand with INSERT IGNORE (autocommit), then one READ COMMITTED transaction locks them with SELECT ... FOR UPDATE in key order, checks the capacity against the committed bookings and writes the rows before COMMIT. Deadlocks and lock wait timeouts are retried with a jittered back-off. Several bookings of one cart are reserved all-or-nothing.
Order flow and hooks
Section titled “Order flow and hooks”| Hook | Use |
|---|---|
pre_add_to_cart |
Validates the picker input (product_data[ID][kv_br]), takes the hold, stores the booking in extra.kv_br, quantity 1 |
generate_cart_id |
One cart line per booking (the line token is part of the id) |
get_cart_product_data |
Booking price (product price for the customer, price rules, guests/places); option modifiers, promotions and taxes apply on top |
check_amount_in_stock_before_check, update_cart_products_pre |
Quantity 1, no stock for booking lines |
delete_cart_product, clear_cart |
Release the holds |
pre_place_order |
Final atomic reservation (skipped for Multi-Vendor child carts) |
place_order |
Binds the bookings to the order line (MV: the parent first, then each child order) |
change_order_status_post, delete_order |
Release / re-take places; incomplete orders get an expiry |
get_order_items_info_post |
The booking as an option line of the order product (order pages, e-mails, documents) |
reorder |
Bookings are not copied by “Re-order” |
gather_additional_products_data_post |
Static picker data of bookable products (storefront) |
update_product_post, delete_product_post, clone_product_post, delete_company |
Product tab save, cleanup, copy |
mailer_send_pre |
.ics attachments |
before_dispatch |
Reminder run on admin activity (fallback) |
Template hooks: products:qty (override: the picker on the product page), products:add_to_cart (override: “Book now”, or “Choose a date” in lists and quick view), checkout:product_options, block_checkout:product_extra, checkout:minicart_product_info, profiles:my_account_menu.
Full page cache
Section titled “Full page cache”The picker markup is static per product (configuration and texts only). Availability, slots and prices come from kv_booking_reservations.availability|slots|quote, JSON GET endpoints that are not in the cacheable dispatches and write no session data. The product page block cache refreshes on writes to the booking tables and includes the licence state in its key.
License check
Section titled “License check”License\Client::isActive() together with Accept online bookings gates the storefront picker and its endpoints, adding bookable products to the cart and manual bookings. Bookings already in a cart are still placed with the capacity check; the calendar, lists, exports, cancellations, reminders and My bookings stay available. The licence check itself runs only in the admin panel or from cron.
Integration notes
Section titled “Integration notes”- A bookable product page shows only the date picker and Book now: the “Frequently bought together” block, the Request a quote button and the Make an offer button of other Kavio Labs add-ons are left out there (a booking needs a date). Adding a bookable product without a date in any other way is refused with a message.
- Read bookings with
Tygh\Addons\KvBookingReservations\Bookings::find($params); check availability withEngine::slots()/Engine::checkRange().