Skip to content

Changelog

What changed in each release of Pre-Order, in terms of what it means for you rather than which files moved.

1.6.1 — 3 October 2026

A fixes-only release. It carries everything in 1.6.0 below.

  • A payment that lands while the module is off is still recorded. Every update switches the module off, and money can arrive in that window: a late gateway callback, or a bank transfer you mark Processing. It used to leave the lines unpaid and the link live, so once you switched back on the customer was reminded to pay, the link could take a second payment, and at the end of the window Pre-Order Expired was written over a paid order. The payment is now recorded against its lines and the link closed, whatever the switch says. See Stop selling pre-orders.
  • Saving a product while the module is off releases nothing. A restock saved in that window used to mark lines ready, move the order and email the customer a payment link the pay page then refused. The product's Pre-Order tab is still saved; save the product again once the module is back on and the waiting orders it covers are released then.
  • An order edit that fails part way no longer loses its pre-order rows. Rebuilding them after OpenCart's order editor runs is now all or nothing: an edit that stopped half way used to leave the order with no dates, no payment mode and no paid state.
  • The wording boxes keep what you type. Each Save used to add a layer of encoding to an & or a quote, so & became &amp;, then &amp;amp;. It is stored as typed now, and the product page shows the terms and the button as text. Wording saved before the update keeps whatever it already held: if yours has an &, <, > or a quote in it, open the box once after updating and correct what you see there.
  • Switching language in the wording boxes no longer signs you out. On a store with more than one language, picking another one used to land on the login page.
  • Names on the Pre-Orders screen read as typed. A product called Salt & Pepper, or a customer, email address or order status with an & in it, used to read Salt &amp; Pepper in the lists.
  • An API user with an empty key is refused. OpenCart's own form will not save one, but a row edited by hand can hold one, and it used to open the API to a caller presenting no key at all.

Two corrections to the documentation ride along. The module's Status switch, which an update turns off, is on Pre-Order's own settings screen rather than in the module list. And uninstalling does not revoke the sweep address's secret: an update is an uninstall and a reinstall, so the memory that keeps the secret across an update brings it back after a reinstall too. New address on the settings screen is the only thing that revokes it.

Nothing to do on update beyond the wording check above. No setting, table or API field changes.

1.6.0 — 2 October 2026

A read-only JSON API, off until you switch it on. Your stock or accounting system can read every pre-ordered line — the product, the date the customer was told, how it was paid for and where it stands — and every payment request: when it went out, whether the customer was reminded and when the link stops working. A request whose window has closed reads as lapsed whether or not your store's scheduler ran. The payment link itself is never readable through it, and nothing can be changed through it. Switch it on under API on the settings screen; a caller signs in as an OpenCart API user under System → Users → API. The API lists every field, and limits and guarantees says what it cannot do.

Nothing to do on update. One new setting, the API switch, which arrives off. No new table, column or permission.

1.5.0 — 29 September 2026

The Pre-Orders screen now says what you owe, product by product. A new Owed by product table, under the counters, has one row for every product and option value you have marked: the units customers are owed and have not paid for, the quantity you hold, and how many you are short by, with the items furthest short first. Download CSV gives you the same table as a spreadsheet, with the ids beside the names, to send to a supplier. It holds counts and catalogue names only, nothing about any customer. See See what you owe, by product.

A pre-order can now end itself when the stock arrives. Switch on End when the stock arrives on the Settings tab, and a product save that leaves every item of the pre-order holding at least one unit beyond what is owed, with no line still waiting, releases what it covers as before and then switches the pre-order off. From then on the product sells as an ordinary one. It is off unless you turn it on, so an updated store behaves exactly as it did. It ends the whole product or nothing, an item that does not subtract stock never ends it, and only a product save triggers it. See End a pre-order automatically when the stock arrives. With it off, a restocked product that is still marked goes on selling as a pre-order. That was true before this release too, and it is now written down in limits.

Copying a product now copies its pre-order settings. The product-level setting goes across as it is, and each option value's setting goes to the copy's option value with the same option and value. An option value that appears twice on a product, on the original or on the copy, cannot be matched and is skipped rather than guessed; the log says how many. Products and copies you already have are untouched. See limits.

The guide to charging in full was wrong, and is corrected. It said a charge-in-full line still shows on the Pre-Orders screen and moves to ready when the stock lands. It does neither: the line is paid at checkout, so it never waits for stock and is not on the live list. OpenCart takes its units off the shelf at checkout, so what such an order still needs from your supplier shows on Owed by product as on-hand below zero. See Charge in full instead of later.

1.4.0 — 21 September 2026

Three more tested releases: 4.0.2.2, 4.0.2.3 and 4.1.0.0. Each has had the full pass (archive, install, use, upgrade over itself, uninstall), including the admin order editor, which is driven differently on the two OpenCart lines. The extension itself did not change. The pass now drives the editor the way OpenCart's own screen drives it, and that is what those releases were failing on.

The settings screen now says what OpenCart 4.1.0.1 has taken away. On that release OpenCart's own guest checkout answers a PHP warning ahead of its reply and the browser cannot read the reply, so a guest who presses Continue sees nothing happen and no pre-order can be placed by one. Customers with an account are unaffected, and so is taking a pre-order from the admin order editor. An extension cannot repair this, and 4.1.0.1 is not claimed. See limits.

1.3.0 — 21 September 2026

The daily sweep has two doors of its own, and Pre-Order now supports OpenCart 4.1.0.4. That release broke OpenCart's own scheduler inside core. Every scheduled task on the store dies before any extension is reached, ours and everybody else's, so on 4.1.0.4 the reminder halfway through a payment window never sent, and nothing said so. An extension cannot repair that fault, but it can go around it. There is now a web address you can have fetched once a day from a host's cron panel or a cron service, and a command you can run from a crontab line if your host gives you a shell:

php extension/preorder/preorder.php

Both run the same sweep OpenCart's scheduler ran, so the reminder and the expiry behave as before. Only the thing that starts the sweep changes. Either one is enough; do not set up both. The lines to paste are in install, and the settings screen shows your store's own sweep address, with a button that gives you a new one if you ever need to.

That address is guarded by a secret. The secret is generated when the extension is installed, it is never shown on a form you can type into, and it survives an update with its value intact, so an address you pasted into a cron service a year ago goes on working across releases. Pressing New address stops the old one immediately, which is why it asks you to confirm. Removing the extension takes the secret with the rest of its settings, so the address stops opening anything on a store that no longer has Pre-Order. Putting the extension back brings the same address back, from the copy of your settings Pre-Order keeps, so nothing needs re-pasting.

The settings screen says what your release has broken, and stops promising what it cannot deliver. On 4.1.0.4 it names the release, says the scheduled job can never fire on it, and points at the two doors that work, instead of listing OpenCart's scheduler among your options as though it were one.

1.2.0 — 21 September 2026

Everything Pre-Order puts in your database about a person is now published field by field, with what removes each one: table, column, why it is there, how long it is kept, and what an erasure does to it. It is at what this holds about a person, generated from the extension's own declaration rather than written beside it, so it cannot describe a column the code does not have or miss one it does. In short, this extension keeps no copy of anything identifying, anywhere. No name, email address, telephone number or postal address appears in any of its four tables. It needs an address only to mail somebody the link that lets them pay when their stock lands, and it reads that address off your own order at the moment it composes the mail. That is why the page reaches a person by joining OpenCart's own order rather than by matching a column of ours.

If you read one thing on that page, read this. A pre-order line or a payment request whose order you have since deleted is unlinked: nothing on it names anybody, and there is no longer an order to reach it through, so an access request cannot find it and the page does not claim it is erasable. The remove-everything button below is the only thing that reaches one.

A new screen answers what do you hold about me for one named person. On Customers → Personal Data you enter an email address and get back every holding, from this extension, from any other Kyvero extension you have installed, and from OpenCart itself. Each extension answers for itself and nothing there decides anything on another's behalf. The screen also prints what OpenCart's own account-deletion flow does and does not do on the release you are running, which you should read before you promise anybody anything. A Remove it button on the same screen takes what each declaration says an erasure takes and keeps what it says is kept, with the reason shown against every line it kept. Here that means every pre-order line and every payment request on every order that person placed goes, and none of your product settings is touched. Opening the screen needs OpenCart's own Modify on customer/customer, because reading out everything a store holds about one named person is at least as privileged as editing their account.

The settings screen also has a button that removes everything this extension holds about people: everybody, not one person. It is deliberately separate from uninstalling. Uninstalling deletes nothing at all, on purpose: an OpenCart update is an uninstall followed by an install, so an extension that dropped its tables on the way out would destroy every live pre-order on a routine upgrade. Removing what is held is therefore something you do on a screen, while you can still see what you are about to lose. The button prints the plan first, with both tables and their real counts, reports what went rather than saying success, and cannot be undone. What goes is every pre-order line and every payment request, including the ones whose orders have been deleted, which nothing else can reach. What stays is every product's pre-order setting and your own settings, neither of which is about anybody.

The new screens come with two permissions, and clicking + gives them to your own group. Customers → Personal Data is access on extension/preorder/customer/personal_data with OpenCart's own Modify on customer/customer behind the act itself. The remove-everything screen carries access and modify of its own on extension/preorder/customer/purge, so you can hand somebody the per-person screen without handing them the one that empties the lot. For any other group, tick them at System → Users → User Groups, and log out and back in.

1.1.0 — 11 September 2026

The three wording boxes are now four, and each is per language. The button caption and the two panel sentences were one box each, so a store selling in two languages had one button caption for both. They are the same three fields with a language select above them, and the subject line of the reminder email joins them. What you already wrote is filed under your store's own language and left exactly as you typed it. If you sell in more than one language, open the wording panel after upgrading and write the others.

Write {order_id} in the reminder subject where you want the order number. Our own subject line used a %s and now uses that token. It means the same thing and survives a per-cent sign: with %s, a subject reading 50% off would have left a customer without their payment link. Anything else in braces is left exactly as you typed it.

Your payment method's position and its on/off switch now survive an update. Pre-Order registers a placeholder payment method, and OpenCart keeps that method's two settings under a setting code of its own. Those two were the only ones Pre-Order was not keeping a copy of, so every update put them back the way they shipped: a method you had sorted to 30 came back at 1, and one you had switched off came back on, on every point release, with nothing anywhere saying so. They are kept now, like every other setting on this page. If you had worked around it by re-sorting the method after each update, you can stop.

Pre-Order can also now read a translation of its own strings once one exists. It works out which of the languages it ships your store should be served, rather than assuming your language code is spelled the way our directories are. It still ships English and only English, so that question has one answer and a single-language store's screens are unchanged. See Limits and guarantees.

1.0.0 — 31 August 2026

The first public release. There is no previous version, so nothing below is a change. This entry is the baseline every later one is measured against.

What ships:

  • a Pre-Order tab on OpenCart's own product form, where a product, or one option value of one, is marked as a pre-order with the date you expect it and the way you want to be paid;
  • two payment modes: charging in full at checkout through your existing payment methods, or taking the order for nothing and emailing a payment link when the stock lands;
  • a panel above the add-to-cart button, the button's own wording and one line under the price on every product card in the store, all three rewordable and none of them needing a template edit;
  • release on save, so entering a product's quantity is the whole trigger for the lines waiting on it;
  • a stand-down when what arrived does not cover everybody waiting, with the shortfall printed beside the orders and sending anyway a button you press;
  • a payment window with one reminder at its midpoint and expiry at its end, and a link that is refused past its window whether or not your scheduler ever ran;
  • Release early, Cancel and Reissue for the lines that need a human;
  • a single Pre-Orders screen with five counters and three lists;
  • the same state and the same live payment link on the customer's own order page;
  • a guest checkout that can pre-order and come back to pay, because the emailed link is the identity.

What it does not do is the shorter list, and the one to read first.

It deliberately leaves two things alone, and they are what make it safe to put on a live store. It does not ration stock: who gets the units when you are short stays your decision, made with the number on screen. It does not touch money either: cancelling a line or letting a window run out emails nobody and refunds nothing.

It runs on OpenCart 4.0.2.0 and 4.1.0.3, and refuses to install below 4.0.2.0 rather than half-working. On 4.1.0.4 the reminder never sends, because a fault in OpenCart itself stops every scheduled task on the store. Everything else works there. See requirements and install.

What an update keeps

Two things are true of every update:

  • Nothing you have taken is lost. No table is dropped, at an update or ever. Your pre-orders keep their dates, their payment modes and the state they had reached; the three order statuses keep the ids your order history points at; and every payment link a customer is holding works again once you re-enable the module.
  • Re-enabling is what restores the automation. The event rows and the daily scheduled row are written when the module is enabled, so until you do that, no pre-order panel appears and nothing is released, requested, reminded or expired.

Your settings come back, with the exceptions below. An update is an uninstall and then an install, and OpenCart deletes an extension's settings at the uninstall step. Pre-Order keeps its own copy of them and puts them back afterwards. They are one set for the whole installation rather than one per store.

These are asked for again rather than put back:

  • module_preorder_status — Whether the module is on is OpenCart's to set, and an extension putting it back for itself is an extension deciding your storefront should start selling something. Switch it back on after an update with the Status switch on this extension's own settings screen, which Extensions > Modules opens with its Edit button: the module list itself has no switch.
  • module_preorder_diary_verbose_until — Detailed logging comes back off after an update, the way a fresh install does. An upgrade is an uninstall and a reinstall, and putting a diagnostic window back is how a store ends up verbose months after the support exchange that asked for it ended.

A setting a release adds does not change what your store does. Its default is what Pre-Order did before the setting existed, so an update never asks you to go and set something to get back the behaviour you already had.

What this cannot tell you is whether a release changed how a setting behaves, as against whether it survives. Nothing derives that from the code, so it is written by hand: a release that changes an answer you relied on says so in its own entry above, as its own paragraph and never among what is new.