Limits and guarantees¶
Pre-Order sells stock that has not arrived yet. This page sets out what that does and does not include, so you can read it before you buy.
At a glance¶
| If you are asking | The short answer |
|---|---|
| Does it decide who gets the units when I am short? | No. Nothing is rationed or queued. When stock lands short, nothing is sent automatically and you decide. More |
| Can a deferred pre-order share a basket with in-stock items? | No. The basket page tells the shopper to order them separately. A charge-in-full pre-order can. More |
| Does cancelling a line or an expired window refund anybody? | No. Nothing is refunded, captured or emailed. Refunds are yours to make. More |
| If I change a product's date later, do existing customers see the new one? | No. The date and payment mode are frozen onto the line when the order is placed. More |
| Does a payment link still work after its window, if my cron never ran? | No. Expiry is worked out when the link is opened. More |
| Do payment links keep working while the module is switched off? | No. The link says it is no longer valid until you switch the module back on. More |
| Can I add an option-level pre-order from the admin order editor? | On the 4.0.2 releases only. On the 4.1 releases the editor takes product-level pre-orders only. More |
| Does the reminder send on OpenCart 4.1.0.4? | Not through OpenCart's own scheduler, which that release broke. The web address or the command runs it there. More |
| Does uninstalling delete my pre-orders? | No. The four tables, the three order statuses and every payment link stay. More |
| Can my stock or accounting system read the pre-orders? | Yes, once you switch the API on: every pre-ordered line and where it stands, and every payment request — never the payment link itself. It cannot change anything. More |
What it guarantees¶
- A pre-order line is a row Pre-Order owns. What the customer was promised (the expected date, whether they pay now or later, and where the line has got to) lives in Pre-Order's own tables, not in an order status. You can rename, move or delete the three order statuses it writes and nothing about the pre-order changes.
- What the customer was told does not move. The date and the payment mode are frozen onto the line when the order is placed. Changing a product's Pre-Order tab afterwards changes what new orders are told, never what an existing customer agreed to.
- A payment link is dead at the end of its window whether or not anything ran. Expiry is worked out when the link is opened, so a store whose scheduler never runs still cannot have a lapsed link paid.
- One reminder, ever. Halfway through the payment window, once per request, recorded so a scheduler that runs twice or catches up three weeks late cannot fire a burst.
- A pre-order is charged at the price it was placed at. Nothing is recalculated when the customer comes back to pay.
- Nothing is deleted when you remove it. See what an uninstall keeps.
What it does not do¶
It does not ration stock¶
There is no allocation, no queue and no first-come cut-off. Outstanding pre-orders exceeding what you have on hand is the definition of a pre-order rather than a fault, so nothing here decides who gets the units.
Instead, when stock lands and you have not got enough for everyone waiting on that item, Pre-Order marks the lines ready and sends nothing automatically. The orders appear under Ready to notify with a sentence saying the units do not cover them, and the button beside it sends anyway. Over- inviting is a decision you make deliberately, with the number in front of you.
It does not release a line whose stock nobody counts¶
An option value with stock subtraction switched off has a quantity OpenCart never moves, so a pre-order on it has nothing to wait for. The product tab says so where you set it, and such a line is only ever released by Release this line on the Pre-Orders screen. The same is true of a product whose stock you do not track.
A pre-order stays one while stock is on hand¶
A product you marked as a pre-order keeps selling as one until you switch it off, however much stock it holds. The storefront decides from what you set on the Pre-Order tab and never reads the quantity. So a restocked product that is still marked goes on taking pre-orders, and a deferred line taken then is not released until the product is next saved, because saving the product is what releases lines.
End when the stock arrives, on the module's Settings tab, switches the pre-order off for you. It is off unless you turn it on, and it has three limits:
- The whole product or nothing. Every item the pre-order covers has to hold at least one unit beyond what is owed on it. One option value still short keeps every option value a pre-order.
- An item with stock subtraction switched off never ends it, because nothing counts its stock.
- Only saving the product ends it. An import, or anything else that changes the quantity without OpenCart's own product save, does not.
See End a pre-order automatically when the stock arrives.
A deferred pre-order cannot share a basket with in-stock items¶
An order carries one payment method, and a deferred pre-order is taken with a placeholder that charges nothing, so a basket holding both a deferred pre-order and an ordinary item cannot be checked out. The shopper is told, on the basket page, to order the two separately.
A charge-in-full pre-order has no such restriction: it goes through your real payment methods, and shares a basket with anything. An ordinary item that has itself gone out of stock still blocks that basket, exactly as it does without this extension.
Only option values from a select, radio, checkbox or image option can be pre-ordered¶
Those are the option types OpenCart gives their own stock quantity. A text, date or file option has no quantity to wait for, and the Pre-Order tab lists only the option values it can hold a row against.
An option value the merchant configured overrides the product wholesale¶
If any option value a shopper selected has a Pre-Order row of its own, the product-level setting is ignored for that line completely. This is what makes "this size is a pre-order and that one is not" work, and it means an option value left on Same as the product contributes nothing rather than contributing the product's answer.
A variant product has no Pre-Order tab, and a copy keeps only what it can match¶
A variant's options belong to its master and its form saves through OpenCart's own variant methods, so the tab is offered on the master only. A tab that could not save would be worse than none. Mark the master, and every variant of it follows. Copying a variant copies no pre-order settings, because a variant has none of its own.
Copying a product copies its pre-order settings. The product-level setting is copied as it is, with its payment mode and expected date. Each option value's setting goes to the copy's option value with the same option and the same value. The copy starts disabled, as OpenCart leaves every copy, so you see the settings before a shopper does.
An option value that appears twice on a product is not copied. When the same
value sits twice under one option, on the original or on the copy, there is no way
to tell which of the two a setting belonged to. That setting is skipped rather
than guessed, the copy's option value is left on Same as the product, and the
kyvero.log tab under System → Maintenance → Error Logs says how
many were skipped. Set those on the copy yourself.
The dates and modes across a line are combined, not listed¶
A line selecting several pre-order option values takes the latest date of them, with no date announced counting as later than any date, and defers if any of them defers. A store cannot promise a ship date it has not got, and when the values disagree, it is safer to defer payment than to charge in full for something the customer is still waiting on.
It does not touch money¶
Cancelling a line, or a payment window running out, changes what is owed and emails nobody. Nothing is refunded, nothing is captured, and no payment your gateway took is reversed. Refunds are yours to make where you already make them.
Pre-order marking is per product, not per store¶
A product marked as a pre-order is one in every store on a multi-store install. Which stores sell it at all is already OpenCart's own Links → Stores setting on the product; Pre-Order adds nothing per store on top of it. The settings (days to pay, the wording, the payment mode a new row starts at) are the module's own, and are set once.
The panel and the card line can be lost to a theme¶
The pre-order panel goes above the add-to-cart button on the product page, and the pre-order line goes under the price on a product card. Both are placed by finding that part of the template. A theme that rewrote the product form, or the price block on a card, loses that panel or that line. The page still renders, and everything about the order itself is unaffected. The button wording and the basket-page notice do not depend on it.
It cannot promise an email was delivered¶
Pre-Order hands the payment request and the reminder to your store's mail engine. Whether they arrive is your host's and your sending domain's business. The Pre-Orders screen is the copy of record, and Reissue is what you press for the customer who says nothing came.
Where the order statuses do not tell the truth¶
The three statuses are presentation. Two paths write an order that is a real pre-order and does not carry Pre-Order Received:
- A charge-in-full pre-order carries your store's normal order status, because it went through a real payment method like any other order.
- A pre-order placed from the admin order editor carries your store's default status. Pre-Order names its own status from its placeholder payment method's confirm step, and the editor does not use one.
In both cases the pre-order itself is correct: the lines are recorded, the dashboard shows the order, the payment request fires and the customer's own order page shows where each line has got to. The Pre-Orders screen is the truth, and the status is a label.
Creating a pre-order from the admin order editor¶
You can put a pre-order on an order from Sales → Orders → Edit, with two limits and one requirement:
- Product-level pre-orders work on every release Pre-Order supports. Option-level pre-orders work on the 4.0.2 releases only. On the 4.1 releases the cart API's add path runs an option-value stock check that reads none of the settings this extension can reach, and refuses the line. Working around it would mean replacing a core controller, which is a worse trade than this sentence.
- The order editor needs your store's API user configured. On the 4.1 releases OpenCart refuses every change the editor makes without one. That is core's rule, not ours, and it applies to every order you edit.
- The mixed-basket rule applies with no merchant exception. You cannot build an order holding a deferred pre-order and an ordinary item, because the storefront payment flow has no way to finish one.
Editing an existing pre-order is safe: OpenCart's editor deletes and re-inserts every line of the order, and Pre-Order rebuilds its rows against the new ones. A line whose product and options are unchanged keeps its date, its mode and the state it had reached; a line whose product or options changed becomes a fresh pre-order at waiting; a line you removed loses its row. The payment link is untouched, because the customer may be holding it.
OpenCart 4.1.0.4: its own scheduler cannot run the sweep¶
That release moved OpenCart's autoloader into a file its own cron.php does not
load, which kills every scheduled task on the store, not only Pre-Order's.
We can state the consequences but not fix them:
- The reminder email halfway through a payment window does not send, and nothing says it did not.
- Nothing moves an abandoned order to Pre-Order Expired. It sits on Pre-Order Payment Requested with a link that is already dead, which is the safe way round: the gate is worked out when the link is opened. Asked to pay, not paid on the Pre-Orders screen is what surfaces those orders.
- Everything else works. Pre-orders are taken, released, requested and paid as normal.
There are two doors out of this, and they are the reason Pre-Order claims the
release rather than refusing it. The sweep is one pass, and OpenCart's
scheduler is only one of three ways to reach it. The other two do not go near
cron.php and work normally on 4.1.0.4:
- The web address on Pre-Order's settings screen, under Sweep address, fetched once a day by a host's cron panel or a third-party cron service.
php extension/preorder/preorder.phpfrom your store's directory, run once a day from a crontab line.
Both are in install, with the lines to paste. Set one of them up and nothing above happens to you.
What neither door does is let anybody run the sweep. The web address carries a secret generated when the extension was installed, compared in constant time, and a store whose secret is somehow empty refuses every caller rather than admitting every caller; the command refuses anything that is not a terminal. That route emails customers and expires their payment links, and an unguarded one would let a stranger make your store do both.
The API, and what it can read¶
Off until you switch it on, under API on the settings screen, and while it is
off every route answers as though this extension had no API at all. Two read
resources: line is one pre-ordered order line — the product, the date the
customer was told, how it was paid for and where it stands — and payment is
the request asking a customer to pay once the stock is in. The API
is generated from what the extension actually answers.
- It only ever reads. Nothing can release a line, send or reissue a payment request, cancel anything or take a payment through it.
- No payment link is readable through it. The link is the money: whoever holds it can pay for the order. It is not a field and not a filter, and whether it still works is the request's state, not the presence of a token.
- A closed window reads as
lapsed, whether or not your scheduler ran. The window is never stored — it is worked out from when the request went out and your days-to-pay, which is also why a lapsed link is refused on a store whose scheduler never runs. The API reads it the same way, so a line can sitlapsedindefinitely on a store with no sweep rather than becomingexpired. Changing days-to-pay moves every open request's deadline at once. - There is no "changed since" filter. Cancelling a line, a request expiring
and the reminder going out all write without a stamp, and
lapsedmoves with the clock. Walking each collection to the end is the synchronisation, and it is resumable from wherever it stopped. - Editing an order gives its lines new ids (see above), so through the API an edited order reads as lines gone and new lines arrived. The order id is the handle that survives.
- There is no money in it. What a customer owes is on OpenCart's own order.
- The credential is OpenCart's own API user, and it is not scoped. One is enough to read every extension's API on the store and core's own order API besides, across every storefront. Restrict it by IP address under System → Users → API, and treat it the way you would treat an admin login.
- Nothing records that anybody read anything. No read log, no per-credential audit trail, no rate limiting.
What an uninstall keeps¶
Removing Pre-Order deletes its event rows, its scheduled row and its placeholder payment method. It deletes nothing else, on purpose: an update in OpenCart is an uninstall followed by an install, so anything cleaned up here would be cleaned up on every version bump.
So these stay: the four tables, every pre-order row in them, the three order statuses your order history still points at, and every payment link a customer is currently holding.
The two ways of removing it behave differently, and the difference matters while you are holding live pre-orders:
- Switching the module off, or uninstalling it from Extensions → Modules, stops the automation: no releases, no payment requests, no reminders, no expiries, and no pre-order panel on the storefront. Outstanding payment links stop working too: the payment page answers only while the module is switched on, so a customer opening one is told it is no longer valid. Nothing about the link is lost, and switching the module back on makes every one of them work again.
- Uninstalling it from Extensions → Installer removes the files, so an outstanding payment link 404s. The data is untouched, and installing it again restores every outstanding pre-order exactly as it was, statuses and tokens included.
If you want the data gone, remove it yourself once you are sure:
DROP TABLE `oc_preorder_setting`, `oc_preorder_order_product`,
`oc_preorder_order`, `oc_preorder_memory`;
Use your own table prefix. Nothing in Pre-Order can do this for you, and that is deliberate.
Language¶
Pre-Order talks to your customers at the moment they are deciding: the button on the product page, the panel under it that says whether they are charged today, and the reminder email that arrives when the stock is late. Which of those a shopper reads in which language is answered, and counted, on the shared language promise page rather than claimed here.
Four points follow, and the first matters most:
- A sentence nobody has translated yet reaches a shopper in English, never blank and never as its own name. Every string here is served with English underneath it, string by string rather than language by language, so a half-finished translation is a page in two languages rather than a page with holes in it. That floor is deliberate: a product page that briefly says Pre-Order in English is better for your store than one showing the name of a setting where a button caption should be.
- The screens you work in are translated as far as somebody has read them and no further, and the rest is English. A string a named reviewer has signed off is served in your admin language; a string nobody has read is served in English rather than blank or as its own identifier; and a string whose English has since been reworded goes back to English until it is read again. Which string is in which state is on that page.
- Four sentences are yours to write, per language, on the settings screen.
The button caption, what the panel says about paying on arrival, what it says
about paying in full, and the subject line of the reminder email. Each is saved
per language and each language on its own, so writing Dutch cannot blank your
English; a box left empty uses our wording, which is shown in it in grey so you
can tell inherited from written. Whatever you write survives an upgrade,
because editing our
.phpfiles underextension/does not: an update replaces those files and takes your change with them. - The body of the reminder email is not one of them, deliberately. It states when the payment link stops working, that the order is not held after that, and that the total has not changed. These are claims about what this extension does, and a rewording could make them false while the extension went on behaving as before. The subject line is yours because it promises nothing. If you had wording of your own you wanted in that email, ask before you buy rather than after.
OpenCart 4.1.0.1: a guest cannot place a pre-order¶
That release reads two fields out of its own guest-checkout form that the form never sends. The step still saves, but OpenCart prints a PHP warning ahead of its reply, and the browser, which is expecting the reply and nothing else, cannot read it. So a guest who fills the form in and presses Continue sees nothing happen, and never reaches the payment step.
- No pre-order can be placed by a guest on 4.1.0.1, in either mode.
- Customers with an account are unaffected, and so is the admin order editor: a pre-order taken over the phone still works.
- Everything else is whole. Releases, the sweep, the payment link, the reminder and every screen behave exactly as the rest of these pages describe.
The fault is OpenCart's, not ours: the two fields are read by OpenCart's own checkout controller, and the same press on a bare 4.1.0.0 or 4.1.0.2 store works. An extension cannot repair it, which is why 4.1.0.1 is not one of the releases Pre-Order claims. OpenCart fixed it in 4.1.0.2, and upgrading to that or newer is the whole of the remedy, and Pre-Order says so on its own screen while you are on 4.1.0.1.
Compatibility¶
The releases Pre-Order has been through a full install-to-uninstall pass on are recorded in the extension's own manifest and stated on its marketplace listing. Below its floor it installs nothing at all and says so on its screen. Above the newest release it has been tested on, it says so and carries on working. Below the PHP floor it installs nothing either, and OpenCart still reports success; requirements says where to look.
Anything not described on this page should be assumed absent. Ask before buying if you are counting on it.