Developer notes
How quantities are stored
Section titled “How quantities are stored”CS-Cart stores quantities as integers everywhere (order_details.amount, products.amount, user_session_products.amount) and casts request amounts with intval(). Prices of order lines are decimal(12,2). The add-on changes no column and no core file:
- A measured cart line always has
amount = 1. The real quantity isextra.kv_fq.qtyin 1/10000 of the unit (1.250 kg = 12500), and the line price is the exact price of that quantity. Soprice × amountis the line total in every place that multiplies them: taxes, promotions, order details, invoices, order editing, the REST API and the line items sent to payment services. - Price math: unit price (after option modifiers, quantity discounts by whole units, catalog promotions) × quantity, rounded half up to the decimals of the primary currency once.
- Stock:
products.amountkeeps whole units = ceil(exact stock). The exact stock is?:kv_fq_products.stockwithstock_synced= theproducts.amountvalue the add-on wrote last. Whenproducts.amountdiffers fromstock_synced, someone else changed the stock (admin, import, API) andproducts.amountwins. Order status changes pass the whole-unit delta ceil(old) − ceil(new) tofn_update_product_amount(), so low-stock e-mails and back-in-stock notifications keep working.
Data model
Section titled “Data model”| Table | Contents |
|---|---|
?:kv_fq_products |
product_id, unit (code), step, min_qty, max_qty, default_qty (ticks = 1/10000 unit), presets (comma-separated ticks), stock (exact stock in ticks), stock_synced, updated_at. |
Cart line / order item extra.kv_fq: qty (ticks), unit, decimals, unit_price, unit_original, qty_text, unit_label, label; order editing adds original_qty. fn_get_order_info() adds kv_fq to each measured item (qty as a decimal string, label, unit_label, unit_price, unit_price_display).
Hooks used
Section titled “Hooks used”| Hook | Why |
|---|---|
pre_add_to_cart |
Reads the decimal amount before core casts it; step/min/max; merges with an existing line; amount = 1 |
add_to_cart |
Stores the checked quantity in the new line |
update_cart_products_pre |
Order editor quantities; a fixed line price follows the quantity |
check_amount_in_stock_before_check (priority 1100) |
Core min/max/step do not apply; quantity rules injected by other add-ons are read in units; exact stock check |
post_check_amount_in_stock (priority 1100) |
Keeps amount 1 after core merges |
get_cart_product_data_pre |
Quantity discounts by whole units (amount_total) |
get_cart_product_data_post |
Unit price → exact line price; subtotal, discount, weight |
change_order_status_before_update_product_amount, update_product_amount_pre, update_product_amount |
Exact stock on order status changes and returns |
gather_additional_product_data_post |
Product page data (static per product) |
get_product_data_post, update_product_post, clone_product, delete_product_post |
Editor, REST API, copies |
get_order_info |
kv_fq on order items |
kv_stock_texts |
Stock numbers printed by other add-ons (“Only 3 left” notes and labels) read the exact measured stock with its unit, see below |
Signatures are identical in 4.17.2 and 4.21.2 (add_to_cart has a fourth argument $_data since 4.18; the handler makes it optional).
Stock texts for other add-ons. Core keeps whole units in products.amount (rounded up: 3.5 kg is stored as 4). An add-on that prints a stock number to shoppers can fire fn_set_hook('kv_stock_texts', $amounts, $texts) with $amounts = product_id => products.amount; for measured products this add-on fills $texts[product_id] with the exact stock and unit (“3.5 kg”). Print the text when it is set, the number otherwise. Neither add-on depends on the other. Urgency & Social Proof Kit and Product Labels & Stickers Pro use it.
Template hooks: products:qty (override, measured products only), products:prices_block (post), products:product_amount (post), products:product_additional_info (post: cart, checkout block, Multi-Vendor separate checkout), checkout:minicart_product_info (override, measured lines only); admin products:update_product_list_qty_count (post), orders:product_info (post: order page and order editor), orders:product_quantity (override, measured items only: “1.250 kg” in the quantity column of the order page; controllers/backend/orders.post.php puts the unit price in the price column).
Schemas: snippets/order_products_table.post.php and packing_slip_products_table.post.php (document product variable with units), exim/products.post.php (7 columns), block_manager/blocks.post.php (cache handlers of the product page and product lists: the add-on’s table and the enabled/licence state).
Full page cache
Section titled “Full page cache”The product page output depends only on the product, its settings and the add-on state (static per product; the products.view main block and product list blocks get the add-on’s table and state as cache keys). Cart, checkout and order pages are not cacheable. Storefront requests write only to the cart and orders like core does.
File map
Section titled “File map”app/addons/kv_fractional_quantities/ addon.xml, init.php, func.php controllers/frontend/checkout.post.php decimal quantities and unit prices on the cart and checkout pages controllers/frontend/orders.post.php customer order page controllers/backend/products.post.php unit list for the product editor controllers/backend/order_management.post.php order editor quantities controllers/backend/orders.post.php order page (admin and vendor panel): unit price of measured items schemas/snippets/*.post.php, schemas/exim/products.post.php, schemas/block_manager/blocks.post.php Tygh/Addons/KvFractionalQuantities/ Qty.php quantity and money math (ticks) Repository.php product settings and exact stock CartHooks.php cart, price and stock hooks View.php template data ProductAdmin.php editor / API / import values Exim.php import and export columns Units.php sale units Gate.php enabled + licence state Documents/ProductVariable.php invoice and e-mail rows License/, Upgrade/ licence client and self-healing upgradesdesign/backend/templates/addons/kv_fractional_quantities/hooks/{products,orders}/…var/themes_repository/responsive/templates/addons/kv_fractional_quantities/hooks/{products,checkout}/…var/themes_repository/responsive/css/addons/kv_fractional_quantities/styles.lessjs/addons/kv_fractional_quantities/func.jsvar/langs/en/addons/kv_fractional_quantities.po