Free demoRun the whole application free for 5 days — in your browser, no installer, no card.

Start the demo
Changelog

What changed, and why

From the first Electron release to the version shipping today. Newest first. Every entry below is a real, dated change to this application — not a rewrite on a different stack.

Latest: 1.4.1 11 August 2026
Version 1.4.1 · 11 August 2026

Financial reports print with a letterhead

A small fix with a real consequence: eight of the nine report tabs were printing with no company name on the page at all.

Nine report tabs, one printing pipeline — except they weren't

Accounting → Reports' nine tabs (VAT Return, Trial Balance, General Ledger, P&L, Balance Sheet, Comprehensive Income, Changes in Equity, Cash Flow, Notes) all print via the browser's own window.print() on the live page, rather than through the application's usual print pipeline. Only the VAT Return tab built its own header; the other eight printed straight into their table with no company name, address or VAT number anywhere on the page.

The Balance Sheet had the wrong kind of header too

A Balance Sheet is a snapshot at a point in time, not a range — every other report in the set covers a period. It was labelled "Period From/To" like the rest, when it should read "As on [date]".

Fixed: a shared letterhead, printed correctly for each report's shape

Company name, address, VAT number and the report's own title now sit above the content for all eight tabs, with either "For the period X to Y" or — for the Balance Sheet alone — "As on [date]". The VAT Return keeps its own equivalent header, unchanged. Pinned by a regression test covering the title map, the as-on/period split, and that every non-VAT tab now has a title.

Version 1.4.0 · 11 August 2026

Batch and lot tracking, with expiry dates

For anything perishable or shelf-life-limited — the kind of stock a restaurant actually holds.

Flag a product to track batches

Once "Track inventory" is on for a product, a further "Track batches / lots with expiry dates" flag is available on the item form.

Split a receipt into batches at the point of receiving

Receiving a lot-tracked purchase-order line no longer takes one quantity — the receiving screen lets it be split into any number of batches, each with its own lot number, expiry date, quantity and cost. A 100-carton PO received as 20 (expiring 15 Aug) + 40 (expiring 28 Aug) + 40 (expiring 31 Dec) posts one goods receipt, three inventory layers, and a GR/IR entry at the batches' actual weighted cost rather than the PO's flat price. Every batch requires both an expiry and a lot number before the receipt can be saved.

FEFO: the earliest-expiring stock goes out first

Consumption drains the batch closest to expiry first, not the batch received first — the distinction that actually matters for anything with a shelf life. Verified against a worked example: issuing 25 units against batches of 20 (expiring first) and 40 (expiring later) drains all 20 of the first batch before touching the second, regardless of which was received first.

Non-lot-tracked items are unaffected

Items without the batch flag receive and consume exactly as before — this is additive, not a change to existing behaviour.

Version 1.3.0 · 10 August 2026

Raise a document from where you already are

And see which orders are still open, without cross-referencing three screens to find out.

+ New Invoice, right on the Sales Invoices page

Previously an invoice could only be started from Sales Orders. A toolbar button now opens the direct-invoice form without leaving the billing page. The same fix landed for Vendor Bills, which had no toolbar at all before this release.

Order tracking, for both sides

Sales Order Tracking and Purchase Order Tracking split every order into the two legs that actually get chased — delivery/receipt and invoice/bill — each shown as Pending, Partial or Complete, with filters for period, status and party, and PDF/Excel export.

One posting path, used by both entry points

The direct-invoice and direct-bill logic was extracted into shared functions now used by both the order-modal route and the new toolbar buttons — same stock consumption, same costing, same journal shape either way. Pinned by regression tests covering both helpers, both modals, both buttons and the tracking maths against a worked example.

Versions 1.2.0 – 1.2.1 · 6 August 2026

Four management-accounting features in one release

Combined party statements, cost centres, a configurable approval workflow, and full POS session control — the biggest single release so far.

POS sessions: opening float to reconciled close

Every register sale now belongs to a numbered session. Split payments across cash, card and bank are supported per sale; at close, expected cash is compared against counted, and the difference posts only once a supervisor approves — as one balanced Cash Over/Short entry. A cashier cannot approve the drawer they counted. One honest limitation carried through from this release: dine-in floor bills do not yet carry a terminal, so restaurant table takings sit outside the drawer reconciliation — counter sales are in.

Approval workflow — authorisation you design, not one we hard-coded

Any number of levels, free-text action names, users and/or roles per level, sequential or parallel stages, per-document-type and per-amount-band routing. A document caught by an active workflow is held as a draft inside the approval instance — the ledger holds nothing until the final level approves. Reject requires a reason, return requires a comment, and the audit trail is append-only. Four templates ship inactive, so nothing changes until one is switched on.

Cost centres — a reporting axis, never an amount

Track income and expense by branch, department or project without touching the chart of accounts or any debit/credit. Tagging travels with a document from order to invoice automatically. Three reports — Movement, P&L by Centre, Budget vs Actual — every one of them keeping an explicit Unallocated column so nothing untagged is hidden.

Combined customer/vendor statement

Where a customer is also a vendor — explicitly linked, never guessed from a name or VAT number — the statement screen gains a Receivable / Payable / Both selector. "Both" merges the two into one chronological statement on a single running balance; the closing figure is a net memo only, and the AR/AP control accounts in the general ledger stay untouched.

Fixed in 1.2.1: cost centre was lost between an order and its invoice

A cost centre chosen on an order line was silently dropped the moment the order was invoiced or billed, and — with "cost centre required" switched on — the posting was then refused with no way to supply one. The tag now travels the whole chain, and the quantity-confirmation screen carries its own cost-centre column so a line that was never tagged can still be tagged there.

Version 1.1.0 · 25 July 2026

Rebrand, and one copy of the app HTML

Housekeeping that mattered: a regression that could silently ship without recent features had crept into the build process, and it was closed for good.

Renamed to Meezan ERP POS

The application was previously "Meezan ERP Restaurant". This release changes the window title, the installer and uninstaller display name, the shortcut name and the release artifact filenames.

Include/exclude VAT pricing, per item

Each product gets a POS price-tax selector — "Excluding VAT, add on top" or "Including VAT, already in price" — with a live net/VAT/gross breakdown on the item form.

The build regression this release closed

Until this release, renderer/index.html was regenerated on every test run from a frozen original file via a transform script. Because that original predated several recent features, running the test suite could silently strip the include/exclude-VAT feature, a ZATCA timestamp fix and the rebrand out of the file that then got packaged. The transform script and the frozen original were deleted — renderer/index.html is now the app and the only copy of it — and the test suite was rewritten to read the file as it actually is, pinning the three features it used to be able to lose.

Version 1.0.0 · 2 July 2026

First desktop release

Wraps the original single-file restaurant ERP/POS in a production Electron shell — the foundation everything above is built on.

Offline licence activation

Node-locked, one year by default. On first launch the app shows a machine code; the vendor signs it into an activation code with an Ed25519 key that never leaves them. Codes cannot be forged, extended or moved to another machine. Activation is mirrored to the backup folder, so a reinstall stays activated.

A hardened Electron shell

contextIsolation, sandbox, and nodeIntegration: false from the first release. A Content-Security-Policy, navigation and window-open guards, single-instance locking, and crash handlers that were not part of the original standalone HTML file.

Uninstall-proof, editable backups

The database is mirrored to Documents/Meezan ERP Restaurant/ as a plain, human-readable JSON file that is never touched by an uninstaller, plus rolling daily snapshots. If a launch finds no live database but a Documents backup exists, it restores automatically.

File-backed persistence, atomic and durable

The database is one JSON file in the OS user-data directory. Writes are atomic (temp file, then rename) with a rolling .bak, and the app falls back to that backup automatically if the primary is ever found corrupt.

Eight issues found and fixed by an adversarial code review

Before release, an adversarial review of the new Electron layer found eight real issues, all fixed and re-tested: silent save failures that could lose data with no warning; a generic file-read/write bridge that accepted any path, since narrowed to the app's own user-data directory; a backup-rotation bug that could let a corrupt primary overwrite the one good .bak; and four smaller findings around navigation guards, write durability and window geometry.

Get 1.4.1

Tell us which platform you run and we will issue the installer with your activation code — or open the 5-day browser demo and see this release running in under a minute.