Developer notes
Money split
Section titled “Money split”For an order with total T, shipping S, payment surcharge X (inside the total) and line subtotals V1…Vn (price × quantity):
base = T − S − Xis shared over the lines pro rata toVi, in cents, with the largest-remainder method, so the shares add up tobaseexactly. Taxes and order discounts are therefore spread pro rata.- A deposit line keeps
round(share × percent)ormin(share, fixed × quantity)as its deposit and the rest as balance; other lines are paid in full now. balance = Σ (share − deposit)anddue now = T − balance, sodue now + balance = Talways.
CS-Cart computes prices, taxes, promotions and shipping as usual on the full price; the add-on never changes prices or order totals. Class: Money::split().
Payment flow
Section titled “Payment flow”get_order_info: whenfn_get_order_info()is called byfn_start_payment()or from a payment script (a file in apayments/directory, including add-on payment scripts and their callbacks), the ordertotalis replaced by the amount due now (first payment) or the balance. All other callers get the full total. The original total is inkv_pob_full_total.finish_payment(before the status change): a paid result (statuses with payment received) of the first payment records the deposit and replaces the status with the deposit status; of the balance it records the balance; a failed balance result keeps the deposit status. For a Multi-Vendor parent order the children are mapped inchange_order_status_child_order.change_order_status_post: manual changes to a paid status (paid in full), to the deposit status (deposit received), to I/D/F (cancelled), back from cancelled (reopened), and the confirmation e-mail.- The balance page (
kv_pre_orders_backorders.pay?t=<token>) changes only the order’s payment method, stores on-site card data exactly like coreorders.repay(core order data, removed by the status rules), callsfn_start_payment()and routes the return to itself (order_placement_routines). - Token: 24 random bytes + an HMAC tag (key:
config.crypt_key); the database keeps the SHA-256 hash and an encrypted copy for the admin panel.
Data model
Section titled “Data model”| Table | Contents |
|---|---|
kv_pob_products |
product_id, preorder Y/N, preorder_limit, button_text, deposit_type G/N/P/F, deposit_value, prev_oos_action |
kv_pob_orders |
one row per (non-parent) order with pre-order or deposit items: kind P/D, state A (awaiting) / B (balance due) / F (paid) / X (cancelled), total, due_now, balance, paid_amount, deposit_paid, release_at, request_at, due_at, token_hash, token_enc, link_sent_at, reminders, overdue_at, refunded |
kv_pob_order_items |
per order item: product, quantity, pre-order flag, release date, share, deposit |
kv_pob_events |
order history (placed, deposit paid, link sent, reminders, released, overdue, payments, e-mails) |
kv_pob_throttle |
rate limiter of the payment page |
The release date is the core products.avail_since; pre-order mode sets products.out_of_stock_actions = 'B'.
get_order_info, place_order, finish_payment, change_order_status_child_order, change_order_status_post, delete_order, calculate_cart_post ($cart['kv_pob'] summary), pre_add_to_cart (mixed-cart rule, limits), allow_place_order_post, gather_additional_products_data_post ($product['kv_pob']), update_product_pre (release date → avail_since), update_product_post, delete_product_post, order_placement_routines, before_dispatch (schedule fallback). All exist with the same arguments in 4.17.2 and 4.21.2.
Template hooks: products:product_labels, products:buttons_block, products:product_additional_info, checkout:checkout_totals, checkout:summary, orders:order_total, orders:repay (storefront); products:tabs_content, orders:details_sidebar (admin).
Caching and the full page cache
Section titled “Caching and the full page cache”- Product output depends only on product data and settings. The block cache of product lists and of the product and category pages gets
kv_pob_productsas an update handler and a key with the license state, the label settings and the hour (release dates pass). - The button text is changed by a small script from a data attribute, so it works with the variation and common-product templates that replace the core add-to-cart block.
- The cart, checkout, payment page and cron URL are not cacheable dispatches. Storefront GETs write nothing to
storage_data; the schedule’s run marks use files while the full page cache is on.
File map
Section titled “File map”app/addons/kv_pre_orders_backorders/ addon.xml, init.php, func.php controllers/backend/kv_pre_orders_backorders.php list, products report, order actions, run, console cron controllers/backend/kv_pre_orders_backorders_license.php "Check now" / license cron controllers/backend/products.post.php Pre-order tab data controllers/backend/orders.post.php order panel data controllers/frontend/kv_pre_orders_backorders.php payment page, cron URL controllers/frontend/orders.post.php customer order page data schemas/menu/menu.post.php, menu_vendor.post.php schemas/permissions/admin.post.php, vendor_multivendor.post.php schemas/block_manager/blocks.post.php schemas/settings/variants.functions.post.php Tygh/Addons/KvPreOrdersBackorders/ Config.php Install.php Products.php Money.php Orders.php Gateway.php Cart.php BalancePay.php Scheduler.php Notifier.php Token.php Throttle.php StorageData.php License/Client.php License/Ed25519.php Upgrade/Synchronizer.phpdesign/backend/templates/addons/kv_pre_orders_backorders/ hooks/products/tabs_content.post.tpl, hooks/orders/details_sidebar.post.tpl views/kv_pre_orders_backorders/manage.tpl, products.tpl, settings/cron_info.tpl, license/*design/backend/css/addons/kv_pre_orders_backorders/styles.less, license.lessvar/themes_repository/responsive/templates/addons/kv_pre_orders_backorders/ hooks/products/{product_labels,buttons_block,product_additional_info}.post.tpl hooks/checkout/{checkout_totals,summary}.post.tpl, hooks/orders/order_total.post.tpl, hooks/orders/repay.pre.tpl views/kv_pre_orders_backorders/pay.tplvar/themes_repository/responsive/css/addons/kv_pre_orders_backorders/styles.lessjs/addons/kv_pre_orders_backorders/func.js, pay.jsvar/langs/en/addons/kv_pre_orders_backorders.poLicense
Section titled “License”The add-on ships the generated License\Client. Gated (switched off without a valid license): the storefront output (labels, info box, button text, cart and checkout summary), the mixed-cart rule, the limits and the deposit record of new orders. Not gated: the payment page, the amount handed to gateways, the payment and status mapping, the schedule (requests, reminders, overdue rule) and the admin pages, so a started customer transaction always completes.