Developer notes
Calendar engine
Section titled “Calendar engine”Tygh\Addons\KvDeliveryDateTimeSlots\Engine is pure date arithmetic (no database, no session) on midnight DateTimeImmutable objects in the store time zone:
| Method | Returns |
|---|---|
earliestDispatch($now, $processing) |
Dispatch day: today when it is a working day and $now is before the cut-off, else the next working day; then $processing working days later. |
deliveryDate($dispatch, $transit, $delivery_days = null) |
Delivery day after $transit delivery days (0 = the dispatch day or the next delivery day). |
eta($now, $processing, $transit_min, $transit_max, $delivery_days = null) |
[from, to] |
currentDeadline($now) |
UNIX time of the cut-off of the current order window. |
schedule($now, $count, $processing, $transit_min, $transit_max, $delivery_days = null) |
The next $count order windows: [until, from, to]. |
availableDates($now, $processing, $method, $slots, $bookings) |
Selectable days (and slots) with available, full, past, remaining. |
Loops are bounded (Engine::MAX_LOOP = 400 days), so a calendar without working days never hangs a request. Repository::engine($company_id) builds the engine for a vendor or storefront (own calendar, else the default; holidays = default + own). Other add-ons can use it:
$engine = \Tygh\Addons\KvDeliveryDateTimeSlots\Repository::engine($company_id);list($from, $to) = $engine->eta(TIME, 2, 1, 3);Full page cache strategy
Section titled “Full page cache strategy”Nothing the add-on prints on cacheable pages depends on the visitor or the session. The product page and the “Next delivery” block print a schedule: the next eight order windows, each with its deadline (UNIX time) and the date labels, computed on the server in the store time zone and language. js/addons/kv_delivery_date_time_slots/func.js picks the first window whose deadline is still ahead (visitor’s clock) and renders the countdown, so the same HTML is correct for every visitor and stays correct for days. The main block of products.view is cached by CS-Cart: schemas/block_manager/blocks.post.php adds the add-on tables as update handlers and fn_kv_delivery_date_time_slots_cache_key() (license state + current hour, so “today”/“tomorrow” labels roll over) as a callable handler. Cart and checkout pages are never cached. Storefront requests write nothing except the booking row of a placed order (own table).
Checkout integration
Section titled “Checkout integration”- The picker is rendered in the template hook
checkout:shipping_methods_list(post) for the chosen method of each product group. Its radioskv_ddts[<group key>][choice]=shipping_id|Y-m-d|slot_idsit inside#shipping_rates_list, so the corefn_calculate_total_shipping_cost()(which posts every checked radio of that element, like pickup points) and the place-order form carry them. controllers/frontend/checkout.pre.phpstores a valid choice in$cart['kv_ddts'][<group key>](shipping_id,company_id,date,slot_id) and, forcheckout.place_order, refuses missing or unavailable choices with a redirect back to the checkout.calculate_cart_content_after_shipping_calculationadds the slot fee to the chosen method’srate(the base rate is remembered inkv_ddts_base_rate, so repeated calculations never add it twice, and a method that is no longer chosen gets its base rate back).allow_place_order_postrepeats the check for other storefront order paths.place_orderwrites the booking row (parent orders are skipped; child orders find their choice by company),form_cartloads it back for admin order editing.
Tables
Section titled “Tables”| Table | Contents |
|---|---|
kv_ddts_calendars |
One row per company (0 = store / marketplace default): work and delivery days, cut-off, processing and transit days, status (A own / D inherit) |
kv_ddts_holidays |
Closed days per company: date, recurring, closes (B both, D dispatch, L delivery), name |
kv_ddts_methods |
Per shipping method and company: mode (N, E, D, S), required, transit (-1 = calendar), extra days, delivery days, horizon, lead minutes, daily capacity |
kv_ddts_slots |
Time slots per method and company: weekdays, from, to, capacity, fee, position, status |
kv_ddts_processing |
Processing days per product (P) or category (C) |
kv_ddts_orders |
One row per order: kind (S slot, D day, E estimate), delivery date, slot and times, fee, estimate range, shipping method name |
| Hook | Use |
|---|---|
calculate_cart_content_after_shipping_calculation |
Slot fee |
allow_place_order_post |
Required / available choice (storefront) |
place_order, form_cart, get_order_info, delete_order |
Booking row of the order |
get_orders, get_orders_post |
Delivery column, filters (kv_ddts_from, kv_ddts_to, kv_ddts_slot_id, kv_ddts_shipping_id, kv_ddts_kind), sorting kv_delivery |
update_product_post, delete_product_post, clone_product, update_category_post, delete_category_after |
Processing time |
delete_shipping, delete_company |
Cleanup |
init_templater_post |
Upgrade synchronizer (only while pending) |
before_dispatch (static, License\Client) |
License checks and notices in the admin panel |
All hooks have identical arguments in CS-Cart 4.17.2 and 4.21.2. Template hooks: products:product_detail_bottom, checkout:extra_list, checkout:shipping_methods_list, orders:totals_shipping (storefront); orders:shipping_info, orders:manage_header, orders:manage_data, orders:advanced_search, products:detailed_content, categories:detailed_content (admin).
Theme hooks (for theme authors)
Section titled “Theme hooks (for theme authors)”Every estimate element (.kv-ddts-eta) carries data-kv-ddts-eta (product, cart, checkout, block), data-kv-ddts-schedule (JSON windows {u: deadline, f: from label, t: to label, d: Y-m-d}), and, after the script ran, data-kv-ddts-deadline and data-kv-ddts-date. The script triggers
$.ceEvent('on', 'ce.kv_ddts.eta', function (data) { // data: {element, context, deadline, seconds_left, countdown, from, to, date}});and sets window.kvDdts.next (the first estimate on the page) and the attribute data-kv-ddts-next on <html>. A header “delivery slot” pill (for example in a grocery theme) can show the text of the Next delivery block (Block Manager, optionally with a time-slot shipping method) or read window.kvDdts.next.from.
Picker classes: .kv-ddts-picker, .kv-ddts-days / .kv-ddts-day (--active, --selected, --full; parts __wd, __num, __mon), .kv-ddts-slots / .kv-ddts-slot (--selected, --full, --past; parts __day, __time, __note, __left), .kv-ddts-nopref. Colours and radius come from CSS custom properties with defaults: --kv-ddts-accent, --kv-ddts-accent-soft, --kv-ddts-line, --kv-ddts-surface, --kv-ddts-surface-muted, --kv-ddts-muted, --kv-ddts-radius. A theme sets them on .kv-delivery-date-time-slots (or :root) to match its palette without overriding the add-on’s CSS.
License check
Section titled “License check”fn_kv_delivery_date_time_slots_is_licensed() (cached per request, never throws) wraps License\Client::isActive(). It gates: the product, cart, checkout and block estimates (Eta), the picker and the stored choice (Checkout::pickers(), storeRequest()), the slot fee (applyFees()), the place-order checks and new booking rows. Not gated: admin pages, stored order data on order pages, invoices and e-mails, the slot board. The block cache key contains the license state.
File map
Section titled “File map”| Path | Purpose |
|---|---|
app/addons/kv_delivery_date_time_slots/addon.xml |
Settings, six tables, install/uninstall functions, snippet templates |
init.php, func.php |
Hooks, license gate, block function, install (document snippet calls), uninstall |
Tygh/Addons/KvDeliveryDateTimeSlots/Engine.php |
Calendar engine |
.../Config.php |
Settings, scopes, time zone, date and time formatting |
.../Repository.php |
Calendars, holidays, methods, slots, processing times, bookings, order rows |
.../Eta.php |
Estimates (product, cart, checkout, block) and the block cache key |
.../Checkout.php |
Picker, choice, fees, checks, order rows |
.../OrderView.php |
Display data of order rows, admin change |
.../Admin.php |
Form normalisation, shipping method lists, slot board |
.../Documents/DeliveryVariable.php, Documents/TemplatePatcher.php |
Document variable kv_delivery, snippet calls in the invoice and order summary |
.../License/Client.php, License/Ed25519.php |
Domain-bound license client (generated) |
.../Upgrade/Synchronizer.php |
Self-healing in-place upgrades (generated) |
resources/snippet_templates.xml |
Snippet “Delivery date and time slot” (Twig 2 and 3) |
controllers/backend/kv_delivery_date_time_slots.php |
Calendar, holidays, method, slots, slot board |
controllers/backend/orders.post.php, products.post.php, categories.post.php |
Order change form, processing time fields |
controllers/backend/kv_delivery_date_time_slots_license.php |
“Check now” and cron license check (generated) |
controllers/frontend/checkout.pre.php, checkout.post.php, products.post.php |
Choice and checks, picker and cart data, product estimate |
schemas/menu/*, schemas/permissions/* |
Menus and permissions (vendors: own data only, company from the session) |
schemas/block_manager/blocks.post.php |
Cache keys, “Next delivery” block |
schemas/documents/order.post.php |
Document variable |
design/backend/templates/addons/kv_delivery_date_time_slots/* |
Admin pages and hooks |
var/themes_repository/responsive/templates/addons/kv_delivery_date_time_slots/* |
Storefront components, hooks, block |
js/addons/kv_delivery_date_time_slots/func.js, admin.js |
Countdown and picker; method page tools |
Cron line of the license check: php /path/to/store/admin.php --dispatch=kv_delivery_date_time_slots_license.check.