Skip to content

Developer notes

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/Synchronizer
design/backend/templates/addons/kv_booking_reservations/ admin views, product tab, settings infos
var/themes_repository/responsive/templates/addons/kv_booking_reservations/ picker, cart lines, My bookings
js/addons/kv_booking_reservations/func.js, backend.js
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.

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

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.

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.

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\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.

  • 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 with Engine::slots() / Engine::checkRange().