
Shared Stock for OpenCart — one stock for several products and option values, no overselling
An OpenCart 4, 3 and 2.3 module that sells one physical item from one stock figure wherever it appears: as a product of its own, as an option value in several lists of a gift box ("Flavour 1…5: Vanilla") or in another box. The cart is checked against the pool as a whole, "Add to Cart" refuses with the quantity left, and two shoppers confirming the last units in the same second do not both get them. The basic version is free; Pro adds packs, history with CSV, "low" and "out of stock" e-mails. Lifetime licence.
- Compatibility
- OpenCart 4.0.2 – 4.1.x (tested on 4.1.0.3 with the pdo driver and 4.0.2.3), 3.0.x (tested on 3.0.5.0) and 2.3.0.2 (PHP 7.0) · default checkout and our One Page Checkout · MySQL / MariaDB · module languages: English, Ukrainian, Russian
- Version
-
v1.0.1 (OpenCart 4)
v1.0.1 (OpenCart 3.x)
v1.0.1 (OpenCart 2.3) - Licence
- one site, lifetime
- Trial
- 7 days, no card, one per site
What Free has,
and what Pro adds
The free version works with no time limit. Pro adds the rest of the features in the table.
Key points
What the shopper sees
The shopper picks the flavours in a box and presses “Add to Cart”.
What is tested and what is not
Tested locally on four OpenCart versions: 79 checks on OpenCart 4.1.0.3 and 4.0.2.3 and 77 each on 3.0.5.0 and 2.3.0.2 for the main scenario, plus separate runs in a browser, with One Page Checkout, order editing, imports and Pro e-mails.

The trial starts when you ask
A fresh install is the free version, nothing switches on by itself. The “Try Pro for 7 days” button → e-mail → the key right in the window and by e-mail.

One key — one site
Moving the store? Unbind the licence on the old domain and activate it on the new one yourself. For studios — keys for 5 or 25 sites, or unlimited.
Technical requirements
OpenCart 4.0.2.0+ and 4.1.x (tested on 4.1.0.3 and 4.0.2.3), 3.x (tested on 3.0.5.0) or 2.3.0.2.
PHP 7.0+ — whatever your OpenCart version needs (tested on 7.0, 8.1, 8.2 and 8.3).
Database MySQL or MariaDB: the lock between checkouts is a MySQL named lock (GET_LOCK). Tested on MariaDB 10.11. On a Galera cluster this lock does not work across nodes.
“Stock Checkout” in the OpenCart settings must be off — otherwise OpenCart does not check stock at checkout and the module does not refuse either.
Store mail is configured (System → Settings → Mail) — for the Pro e-mails.
Module languages: English, Ukrainian, Russian.
Frequently bought with Shared Stock for OpenCart
4 modules in one order — 40% cheaper than separately


Nova Poshta Premium — a Nova Poshta module for OpenCart 2.3, 3.x and 4.x

LiqPay — Card Payments for OpenCart 2.3, 3.x and 4.x

Telegram notifications and Viber/SMS for customers for OpenCart
Full module description
Shared Stock for OpenCart is a module by the CatCode studio for a store that sells one physical item in several places of its catalogue. A Vanilla bar on its own — and the same flavour in a gift box where the shopper picks a flavour in five lists, “Flavour 1…5”. The same item in another box. OpenCart keeps the stock of every product and every option value separately, so the store owner copies figures by hand — and still sells the last unit twice.
Shared Stock joins such places into a pool — one stock figure they all sell from. A pool member can be a whole product or a single option value. The cart is checked against the pool as a whole: a box with five “Vanilla” picks, quantity 2, takes 10 from the pool. A sale of any member takes from the pool, and every member shows how much the pool can still cover. Two shoppers confirming the last units in the same second do not both get them.
This is not a duplicate of Option Combinations. Option Combinations keeps the stock of option combinations inside one product (size × colour). Shared Stock covers a different scenario: one stock for different products and option values — the same flavour as a product of its own, in the five lists of a box and in another box. The first module does not share stock between products; the second does not track combinations inside a product.
What the shopper sees
The shopper picks the flavours in a box and presses “Add to Cart”. If, together with what is already in the cart, the pool is not enough, OpenCart does not add the product and a clear sentence appears above the button: how many are left, or that all of them are already in the cart. A value the pool can no longer cover disappears from the option list like any “out of stock” value.
If the pool went down while the product sat in the cart (another shopper bought first), the cart marks the line with *** and blocks checkout — the standard OpenCart behaviour for stock, only counted by the pool.
What the admin gets
- Catalog → Shared stock: pools with their stock, the units held by unconfirmed orders and what is available; creating a pool. An empty new pool takes the stock of the first member you add.
- Pool page: “Add / take (±N)” relative to the current figure — a delivery booked while orders come in is never lost; “Set to” for a stock count; the e-mail threshold (Pro); members with their OpenCart quantity; product search and adding a whole product or a single option value; the list of holds by unconfirmed orders.
- Product form: a line under the “Quantity” field with the pool name. A new figure in this field or in an option value quantity sets the pool, an old figure from a form opened long ago does not.
- “Re-sync quantities” — after a CSV import or another module that writes quantities directly: mirrors show the pool again, members of deleted products are removed.
How it works, step by step
- You create a pool (for example “Vanilla”), set the stock and add members: the whole bar and the “Vanilla” value from every list of the box. The OpenCart quantity of every member becomes a mirror of the pool.
- The shopper adds a product to the cart. The module counts how many units of each pool the whole cart asks for, taking into account what unconfirmed orders of other shoppers hold, and refuses with an explanation if there are not enough.
- At the confirm step — as a request of its own or inside the OpenCart 4 checkout page and One Page — the module takes a database lock, checks the cart against the pool once more and holds the order units. Another shopper confirming in the same second waits for their turn and sees a smaller figure. If the queue takes longer than 10 seconds (configurable), the shopper gets a refusal rather than a risk of selling twice.
- When the order enters a processing or complete status, the module takes the units from the pool — exactly once per order line — and updates the quantity of every member. Cancelling returns the units.
- A hold of an unconfirmed order lives for 60 minutes (configurable); after that its units are available to other shoppers again.
What is tested and what is not
Tested locally on four OpenCart versions: 79 checks on OpenCart 4.1.0.3 and 4.0.2.3 and 77 each on 3.0.5.0 and 2.3.0.2 for the main scenario, plus separate runs in a browser, with One Page Checkout, order editing, imports and Pro e-mails. Version 1.0.1 went through the same set, plus five runs in a row of simultaneous checkout page loads (default and One Page) on OpenCart 4.1 and 4.0.2.3 — exactly 2 orders out of 8 every time, the pool never below zero — and 24 combinations of store language and shopper language for the “add to cart” message. Test servers stood in for the licence server and mail.
Limits worth knowing. The protection against simultaneous shoppers sits at the order confirm step — both when it runs as a request of its own and when OpenCart 4 or our One Page opens it inside the checkout page. A third-party one-page checkout that writes the order bypassing this step checks the cart without the lock; even then the module writes the hold only when the pool covers it. An order paid after its hold has expired (60 minutes by default) takes from the pool even below zero — just like OpenCart without the module; this shows in the pool history. Not tested: payment gateways with a bank callback, third-party one-page checkouts (other than ours), working together with Option Combinations, OpenCart 4 product variants (master / variant), MySQL 8 and Galera clusters.
Under the hood
- The pool lives in its own table. Member quantities in OpenCart only show how much the pool can still cover; checkout counts by the pool.
- One take per line. An order line takes from the pool once (a conditional update in the database), so a repeated status change or a repeated cancellation doubles nothing.
- Holding at confirmation. An order that reached the confirm step holds its units; the same shopper reopening the step replaces the hold instead of adding a second one.
- No core edits and no OCMOD patches — only OpenCart events; one library for three builds, code compatible with PHP 7.0, works with the pdo database driver of OpenCart 4.1 too.
- The licence is a separate settings group, so saving the settings does not touch it.
- Uninstall removes the module events and tables (you can keep the data for a reinstall).
How to install
- OpenCart 4: Extensions → Installer → upload
cc_sharedstock.ocmod.zip(do not rename the archive) and press “Install”. OpenCart 3: Extensions → Installer →cc_sharedstock-oc3.ocmod.zip→ “Install”. OpenCart 2.3: Extensions → Installer →cc_sharedstock-oc2.ocmod.zipif FTP is enabled in the store settings; otherwise upload the contents of theupload/folder from the archive to the store root. - Extensions → Extensions → Modules → Shared Stock → “Install”.
- Catalog → Shared stock: create a pool and add members — a whole product or an option value.
- Set the pool stock or leave the field empty — the pool then takes the stock of the first member you add.
- For Pro: paste the licence key from the e-mail after payment, or start the trial on the “Licence” tab of the module settings.
Questions
about the module
Didn't find the answer? Message us on Telegram and we'll reply within a business day.
How is this different from Option Combinations?
Option Combinations keeps the stock of option combinations inside one product. Shared Stock is for when the same item sells in several products or several option lists: a single Vanilla bar, Vanilla in each of the "Flavour 1…5" lists of a gift box, the same flavour in another box. So it is not a duplicate but a different scenario: one stock for different products and options. We have not yet tested both modules together in one store.
Does it really prevent overselling when two people pay at the same time?
Yes, at the confirm step: the order holds its units under a database lock, the second shopper waits and sees that the pool is no longer enough. In the test 8 shoppers confirmed 4 units each from a pool of 10 at the same time — exactly 2 orders went through and the pool never went below zero; without the module the same test let all of the first 4 out of 4 through. Since version 1.0.1 the same protection covers the case when OpenCart 4 or One Page writes the order while the checkout page loads: 8 simultaneous page loads — exactly 2 orders, in 5 runs in a row.
When are units taken from the pool?
When the order enters a processing or complete status — the same moment OpenCart takes product stock. Cancelling returns the units, a second cancellation returns nothing again. An unconfirmed order only holds its units for the time set in the settings (60 minutes by default).
What happens to a product quantity once it joins a pool?
The member quantity in OpenCart becomes a mirror of the pool and is kept by the module. An empty new pool takes the stock of the first member you add, so the figure is not reset to zero. A new figure typed into the "Quantity" field of a product or an option value sets the pool.
A CSV import overwrote the quantities — what now?
The storefront keeps counting by the pool, so it will not sell more than there is. Press "Re-sync quantities" on the pools page and the mirrors show the pool figure again. If the import carries a new real stock figure, type it into the pool.
Does it work with your One Page Checkout?
Yes, we tested them together on OpenCart 4.1, 4.0.2.3, 3.0 and 2.3: an order through One Page, a refusal when the pool became smaller than the cart, and simultaneous confirmations, including One Page writing the order while the page loads.
Which languages?
The module admin is in English, Ukrainian and Russian, and messages to the shopper are in the language they picked on the storefront (since version 1.0.1 on OpenCart 3 and 2.3 as well).
Is the licence yearly?
No. For OpenCart it is a one-time payment and a lifetime licence, and one licence covers all three builds: 4.x, 3.x and 2.3. Pools, the cart check and the protection at confirmation are in the free version with no time limit.
No reviews yet. Be the first.
No questions yet. Ask one — we answer within 24 hours.
Not quite what you are looking for?
We build custom modules for WordPress, WooCommerce, OpenCart and Shopify. Tell us about the task and we'll prepare an estimate.
Order a custom module
Buying the module
—



