Settings¶
Product Bundles keeps its settings in OpenCart's own setting table, under the
module_product_bundles group. You set them at
Admin > Extensions > Extensions > Modules > Product Bundles.
Each key below carries where it applies. per store means a multi-store install can hold a different answer per storefront, and both are honoured: a read takes what that store holds, then what the default store holds, then the shipped default. install-wide means one thing serves every storefront, and the key's own description names that one thing.
Scope¶
| Key | Default | What it does |
|---|---|---|
module_product_bundles_statusinstall-wide |
0 |
Whether bundles are sold and shown at all. Set by the Status switch on this extension's own settings screen. Off takes every bundle off sale, the way an uninstall does: each bundle's carrier product is disabled, and nothing of Product Bundles runs on the storefront, in the cart or on an order. Your bundles, their components and every order's history stay exactly where they are, and switching it on puts each bundle back on sale or not as its own Status says. While it is off, Product Bundles does not guard Catalog > Products either: a product a bundle holds, or a bundle's carrier, can be deleted or copied there. Nor does it move component stock for an order whose status changes: an order placed with it on that reaches Processing, or is cancelled, while it is off moves no component stock either way. Install-wide because what it switches is this extension's rows in OpenCart's own event and startup tables, and neither of those has a storefront column. |
Surfaces¶
| Key | Default | What it does |
|---|---|---|
module_product_bundles_surfacesinstall-wide |
product_card,bundle_list,review_wording,cart_notice,account_order,order_email,returns_portal |
Which storefront surfaces a bundle is allowed to speak on, as a ticked list. Every one is on to begin with, which is exactly what Product Bundles did before this setting existed. Clearing one puts that surface back to OpenCart's own behaviour and nothing else: a shopper can still reach a bundle, configure it, buy it and be charged the right price. The surfaces are the bundle card on product listings, the store's own Bundles page, the reworded review copy, the cart and mini-cart notice about a line that can no longer be packed, the contents on the customer's order page, the same in the order emails, and the same on Returns Portal's screens. Install-wide for the same reason the switch above is: these are event rows, and an event row fires for every storefront. |
Bundles¶
bundle — install-wide
One row per bundle: what it is called from the catalogue's point of view, what it costs, what it weighs and whether it is on sale. Built at Catalog > Bundles, never on this screen. Install-wide because the oc_product carrier row a bundle is projected onto is one row shared between storefronts; which storefronts actually offer it is product_bundles_to_store below.
model— The bundle's own model, shown beside it and used to group it in Reports > Products Purchased. Starts at empty.image— The bundle's own image. Component images are shown separately, as the contents. Starts at empty.price_mode— Whether the price is a discount off what the components come to, or a fixed amount. Never a blend, and both numbers are kept either way so switching modes to look at the other one loses nothing. Starts atdiscount.price— What the whole bundle costs, read only when the pricing mode is fixed. Starts at0.0000.discount_type— Whether the discount is an amount off or a percentage off, read only when the pricing mode is a discount. Starts atamount.discount— How much comes off the summed component price, read only when the pricing mode is a discount. Starts at0.0000.tax_class_id— The tax class the whole bundle is taxed under. Component tax classes are not consulted. Starts at0.manufacturer_id— The bundle's own brand, which is what puts it on a brand page beside that brand's products. Zero is OpenCart's own none. Starts at0.weight— What the bundle weighs. Left empty the components are summed, which is the answer for anything shipped in its own packaging; a number means this bundle is repacked into one box and weighs that. Empty rather than nought, because nought is a real weight. Starts at empty.weight_class_id— The unit the typed weight is in. Starts at0.length— The packed bundle's length. Dimensions are never summed — two 10cm cubes are not a 20cm cube — so they are yours to set outright. Starts at0.00000000.width— The packed bundle's width, for the same reason. Starts at0.00000000.height— The packed bundle's height, for the same reason. Starts at0.00000000.length_class_id— The unit the typed dimensions are in. Starts at0.points— What the bundle costs a shopper in reward points, if you sell for points at all. Starts at0.status— Whether the bundle is on sale. Disabling one hides it and its reviews until you enable it again, and never deletes anything. Starts at1.date_available— The day the bundle goes on sale. A new bundle starts at today, so it is on sale as soon as you save it. Starts at empty.sort_order— Where the bundle sits among products in a listing, exactly as a product's own sort order does. This is where you put bundles above or below ordinary products, and it is per bundle rather than store-wide on purpose. Starts at0.
description — install-wide
What the bundle is called and what it says, one row per language, exactly as OpenCart stores a product's. These are yours and always were: Product Bundles ships English and translates none of your words. A language with no row falls back to nothing rather than to another language's prose, so a bundle is only ever described in words somebody wrote for that language.
name— The bundle's name. Shown wherever the bundle is, and on the order line it sells as. Starts at empty.description— The bundle's own description. Component descriptions are never concatenated into it. Starts at empty.meta_title— The page title. Required: the bundle form refuses to save it empty, as core does a product's. Starts at empty.meta_description— The sentence a search engine may print under the bundle in its results. Left empty, nothing is emitted rather than a description invented from the bundle's name. Starts at empty.meta_keyword— Keywords, as OpenCart carries them on a product. No search engine has read them for years; the field is here because a product has one. Starts at empty.
component — install-wide
What is in the box: one row per component product. The same product twice is one row with a quantity of two and never two rows, which the table enforces — two rows for one product would have to be summed by every reader, and the first reader to forget would undercharge or under-decrement.
quantity— How many of that component one bundle holds. A cart wanting two bundles wants twice this of it, and the stock decrement multiplies the two. Starts at1.sort_order— Where the component sits in the list of contents. Starts at0.
to_store — install-wide
Which storefronts a bundle is offered in — the one thing about a bundle that really is per store, and it is set on the bundle rather than on this screen. A new bundle starts in the default store. The carrier's own store rows are written from these and are never wider, because OpenCart's cart drops a line that is out of store before Product Bundles sees it at all.
store_id— A storefront the bundle is sold in. A new bundle carries the default store and nothing else. Starts at0.
to_category — install-wide
Which categories a bundle appears under, mirrored onto its carrier the way OpenCart stores a product's. The bundle's set is the authoritative one: OpenCart's own product save deletes a product's category rows before writing back whatever it is handed, so a set kept only on the carrier is a set the next save clears.
category_id— A category the bundle is listed in. A new bundle is in none. Starts at empty.
to_filter — install-wide
Which filters a bundle answers to, mirrored onto its carrier for the same reason the categories are. Both are a bundle's findability and neither changes what is in the box.
filter_id— A filter the bundle matches. A new bundle matches none. Starts at empty.
reward — install-wide
What buying the bundle earns a shopper in reward points, per customer group. The one figure on the bundle form that nothing derives, and deliberately so: a bundle sold at a third off would otherwise award the full points of everything in the box and you would be paying for the discount twice. A customer group with no row earns nothing, which is what OpenCart does for a product.
points— Points that customer group earns for buying the bundle once. Starts at0.
Layout module¶
| Key | Default | What it does |
|---|---|---|
module_product_bundles_module_limitinstall-wide |
4 |
How many bundle cards the Product Bundles layout module shows wherever you place it, from 1 to 12. On a product's own page it lists the bundles that product is in; anywhere else it is a shelf of your bundles in the Bundles page's own order. One number for every placement, because the module is single-instance: OpenCart keeps no per-placement settings for it. Install-wide because a placement is a row of OpenCart's own layout table, which has no storefront column. |
Advanced¶
| Key | Default | What it does |
|---|---|---|
module_product_bundles_diary_verbose_untilinstall-wide |
0 |
When detailed logging stops, as a unix timestamp, and 0 is off. Turning Detailed logging on from this extension's settings form stores the moment two days from now; the writer compares that against the clock every time it is asked for a DEBUG line, so the window closes on its own with no scheduled task and nothing to clean up. While it is open this extension records what it did in far more detail, and the shared diary consequently holds less history. |
module_product_bundles_api_enabledinstall-wide |
0 |
Whether the extension answers API requests at all. Off, every API route answers 404 api_disabled in the API's own JSON envelope, so an extension with its API off is shaped like one that has none. Read once for the whole installation from the default store rather than per store, because the one thing it serves is OpenCart's own API user, which has no store of its own. It is a separate switch from the extension's own Status, and the two are read independently: the API answers whether or not bundles are on sale, because what each order sold inside a bundle is the merchant's own record and a storefront switch should not hide it. The API only ever reads; no bundle can be created or changed through it. |
What you cannot change, and why¶
These are fixed on purpose. Each one is a decision with a reason beside it rather than a setting nobody got round to adding.
Surfaces¶
The surfaces above are the ones a bundle speaks on. The rest of what Product Bundles registers is not offered as a tickbox, because none of it is a place a bundle is shown — it is what makes a bundle sellable at all. Pricing a bundle in the cart, refusing a carrier nobody configured, recording what a line contained as the order is created, moving each component's stock on the status the order reached, redirecting a carrier's product page to its bundle page, keeping a bundle out of the admin order editor, and answering OpenCart when it asks a carrier for its stock or its subscription plan: switching any of those off would leave a storefront that sells a bundle it cannot price, pack or record. That is not a preference, and a settings form is not the place to offer it. The one switch that turns all of it off is the module's own, above.
How much of a chosen option value a contents row shows is OpenCart's own number rather than one this extension gets to pick. The account order page, the confirmation email and the store owner's alert each cut an option value before handing it to the template, and a contents row that arrived uncut would be the one row on the page running on past its neighbours. Returns Portal's own screens cut nothing, so the rows handed to those are uncut for the same reason — there is nothing there to line up with.
| Rule | Value |
|---|---|
| Characters of an option value a core surface shows | 20 |
| What is put in place of the rest | .. |
The markup a bundle card is drawn with, and the slots the cart and mini-cart notices are put into, are this extension's and not settable. A field a merchant types markup or a pattern into turns a support conversation about a theme into a support conversation about what they typed, which is worse for both of us. The honest route is a template override, which this repository does not offer yet; a theme this does not sit well in is a bug report worth making rather than a setting worth having.
Advanced¶
Where a bundle's own URL row sorts against the route row it shares a table with is fixed, and it is not the same question as where a bundle sorts in a listing. OpenCart resolves a URL by walking its keyword rows in this order, and the two numbers below are what make /starter-kit the bundle rather than the listing page; a test pins the pair. Where a bundle sits among your products is yours to set, per bundle, as the bundle's own sort order on the bundle form.
| Rule | Value |
|---|---|
| Where a bundle's own URL row sorts | 1 |
| Where the route row sorts | -1 |