Progress Report · For Michal

SlimOffice, on the web — where the port stands

A modern browser front-end for the Delphi 2009 SlimOffice ERP, running on the real demo database and reproducing each form's logic from the original source. Here's what's built, how we proved it works, and what's deliberately left.

Span: 11–13 Jul 2026 (from commit 1) Commits: 74 · 40 features, 10 fixes Tests: 280 passing, 0 failing Status: demo-ready, browser-verified

01 At a glance

280
Tests passing (0 fail)
11/14
Business areas live
77
Codebooks / catalogs
~11k
Lines of new app code

The full workflow runs end to end in the browser: log in → issue an invoice → compute VAT → post to the ledger (balanced) → move stock → depreciate assets → close via the ledgers → view a payslip. Every calculation engine was checked against the numbers the original desktop actually produced — matched to the haléř.

02 The full list — every screen that's built

Every module below runs on the real demo database (204 tables imported from the original MS-SQL dumps). The badge shows how many real records each screen is working with — this is live data from the actual SlimOffice demo company, not test fixtures.

ScreenWhat it doesLive dataDepth
Prodej · Sales
FirmyCompany catalog — full detail card, 6 child tabs (bank accounts, contacts…), IČO/DIČ validation, ARES/VIES lookup29 firmsCreate · Edit · Delete
FakturyInvoices — issue, VAT recompute, post to ledger, print, storno, copy139 docsFull pipeline
Sklady · Warehouse
ZbožíProduct catalog — stock card with live price resolver, stock levels, movement history19 itemsCreate · Edit · Delete
Pohyby zbožíStock movements — create receipt/issue, posts weighted-average cost to the warehouse; delete recomputes30 movesCreate · Delete + engine
Účetnictví · Accounting
Účetní deníkGeneral journal — line-level entries, balanced MD=Dal double-entry1 411 rowsCreate · Edit · Delete
Účtový rozvrhChart of accounts — typed, browsable1 605 účtůBrowse
SaldoOpen-items balance — Σ debit = Σ credit, balances280 itemsBrowse
Pokladna · Cash
Pokladní dokladyCash documents — create/edit, cash double-entry posting, always balances, numbering37 docsFull pipeline
Objednávky & Zakázky · Orders
ObjednávkyPurchase orders — create/edit with lines, numbering, supplier autofill13 ordersCreate · Edit · Delete
ZakázkyJobs — create/edit, customer autofill15 jobsCreate · Edit · Delete
Banka · Bank
Platební příkazyPayment orders — create/edit (header-only)34 ordersCreate · Edit · Delete
Bankovní výpisyBank statements — create/edit with transaction lines26 stmtsCreate · Edit · Delete
Majetek · Assets
MajetekAsset cards — detail + a computed depreciation plan (tax + accounting) on the card10 assetsCreate · Edit + engine
DPH & Mzdy · VAT & Payroll
DPH přiznáníVAT return — the real filed returns with form lines4 returnsBrowse
Zaměstnanci / VýplatniceEmployees + payslips — full net-pay breakdown (hrubá → pojistné → daň → čistá)68 emp · 1 281 linesRead-only
Číselníky · Codebooks (one shared engine)
77 catalogsReference tables — numbering series, VAT codes, PSČ, OKEČ (1135), payment titles, depreciation groups… all browse + edit with zero per-form code77 codebooksCreate · Edit · Delete
Cross-cutting · Every list & document
Grid featuresPer-column filter row, full-column sort, load-more paging, XLSX export, per-user column picker, print-to-reportall listsShipped

03 How finished is it?

"Finished" depends on what you count. The raw form count is the least meaningful number — most of those forms are trivial pop-ups, or collapse into one shared feature. The honest picture is that the hard part — the calculation engines — is essentially done, and roughly half the meaningful application is built.

Built & verified Partial / read-only Deferred by decision
Core business engines numbering, rights, pricing, VAT, stock, ledger posting, depreciation
~95%
The actual hard work of the port. All eight engines ported from Delphi source and checked number-for-number against the real data.
Business areas Prodej, Sklady, Účetnictví, Pokladna, Banka, Majetek, DPH, Mzdy…
79%
11 of 14 areas live. Not built: Nákup (purchase invoices), System admin, and the tenant-config editor — desktop-era or out-of-scope concerns.
Significant forms the plan's real target — 158 meaningful forms
~50%
Document, catalog and engine forms across the live areas. The honest "how much of the app" number.
Raw form count 923 Delphi form files — mostly filters & dialogs
~18%
Misleading: 159 of these are filter pop-ups (one shared feature covers all), 216 are "detail" halves of pairs, and ~150 are the out-of-scope payroll calc screens.

04 Where we are on the full-app timeline

The planned roadmap (P0–P3) is complete; two showcase phases were added on top. What remains is a short tail — each item is either a deliberate scope decision or blocked by the demo data having nothing to drive it.

P0 · Foundation Shipped

Data import (42 → 164 tables, zero silent loss), the DFM-to-spec pipeline, server-driven grids, auth scaffolding, and the parameter cascade. Everything that removed a "silently wrong at scale" trap.

P1 · Core engines Shipped

The real port: document numbering, login & rights, pricing (9-tier), the VAT/totals engine, the stock engine, MD=Dal ledger posting, depreciation, and zaúčtování — all parity-tested against real data.

P2 · Breadth Shipped

Every named module: Pokladna, Objednávky, Zakázky, Banka, Účetnictví (rozvrh + saldo), DPH přiznání, plus the codebook catalogs.

P3 · Cross-cutting Shipped

One implementation each, every list: XLSX export, Kopie, column customization, print reports, load-more paging.

Showcase + hardening Current

Mzdy read-only (payslips), Bank statements create/edit, 18 more codebooks, two adversarial bug-review passes (11 fixes), and a full browser walkthrough of all 16 modules — 0 console errors.

Remaining tail By decision

Payroll gross-to-net calc (a 27,000-line tax engine — kept on the desktop), the sales-doc → stock auto-issue link (no demo document uses it), and admin/tenant config. None is a defect; each needs a business decision or has no data to run on.

05 How it's tested — the method

Static test data alone gives false confidence. So the testing doctrine has four layers, each catching a class of problem the others miss. 280 automated tests across 31 suites, plus a live browser walkthrough. Here's what each layer actually does.

Layer 1

Recompute-parity

Where the original database stores a calculated result, we recompute it from the raw inputs and diff against what the desktop actually saved. Not "looks right" — identical to the haléř (Czech cent).

e.g. replay all 30 stock movements from zero → 13/14 warehouse rows match exactly

Layer 2

Scenario replay

Dumps only hold end-states, so we replay stateful sequences — create → edit → storno → re-create, concurrent number allocation, failed-save rollback — and assert the invariants pulled straight from the Delphi code.

e.g. a failed save must release its document number — no gaps in the series

Layer 3

Adversarial review

Independent review passes (including a second AI, Codex) hunt for bugs, each finding re-verified against the original source before we accept it. Two full passes ran; every confirmed bug is listed in section 07.

this is how the permission hole and the FX money bug were found

Layer 4

Live browser walk

A headless Chrome drives the real app — logs in, visits all 16 modules, watches for any console error, screenshots the result. Catches UI bugs the API tests can't see.

this caught the Banka list crash the 280 tests had missed

06 What definitely works — and how we know

Each engine below, with its exact parity result. "Verified" here means the same numbers the original desktop computed and stored, to the haléř — measured, not asserted.

CapabilityStatusHow it was proven
Invoicing & VAT Verified Full VAT/totals engine. Header + rate breakdown match the stored records for 49 / 55 real documents to the haléř; the 6 exceptions are diagnosed and pinned.
Ledger posting (MD=Dal) Verified 28 / 30 posted invoices reproduce the stored double-entry posting exactly; the 2 others are reversal-history docs a forward engine doesn't replay.
Stock movements Verified Weighted-average costing engine. 13 / 14 warehouse-state rows recompute to the haléř; the 14th is a known 2005 data error in the dump.
Asset depreciation Verified All Czech methods (accelerated, straight-line, time-based). Every standard asset matches to the koruna, including the spec fixtures.
Pricing (9-tier) Verified Individual-price resolver with currency + discount tiers; parity probes on the real dump match the desktop's chosen price.
Money rounding Verified Faithful port of Delphi's rounding rule — 0 divergences vs a reference over ±2 million inputs.
Login & permissions Verified Rights model ported line-for-line from the original — including its own quirks, replicated rather than "fixed".
Payslips (Mzdy) Read-only Shows what the desktop computed (68 employee-periods, 1281 lines). Every stored payslip's net-pay identity balances to the koruna. No gross-to-net calc — by design.
Documents (Pokladna, Objednávky, Zakázky, Banka) Verified Create / edit / delete with numbering allocation; round-trip tested + exercised end-to-end over live HTTP.
Whole app in a browser Verified Headless-Chromium walk of all 16 modules: real data everywhere, 0 console/page/request errors.

07 Features that work differently — or that we fixed

The special section you asked for. Two kinds of thing live here: places we deliberately deviated from a literal 1:1 copy (blue / amber), and real defects that testing exposed and we fixed at the root (red). Every one is documented — none is a surprise waiting in production. In total this session's review passes found and fixed 11 confirmed bugs.

Rewritten · cleaner

Deleting a stock movement

The original never reverses stock on delete — it relies on a manual full-warehouse rebuild. We instead recompute only the affected goods automatically. Same end result, no manual step.

verified: create→delete leaves the whole stock table byte-identical

Fixed · was a security hole

Editing someone else's document

The "own-records-only" permission check compared the editor's ID to itself — so it always passed, letting any user modify records they shouldn't. Now it checks the record's real owner.

found by adversarial review · fixed & regression-tested

Fixed · silent data loss

Renaming a catalog code

Saving with a changed key silently wrote to a phantom row and dropped the edit. The key is now immutable on update — the change always lands on the right record.

one root-cause fix across catalogs + firmy + zboží

Fixed · wrong money on FX

Foreign-currency stock receipts

Last-purchase-price was double-counting the exchange rate, and the overhead split was off by the rate. Both matched the original's stored proc once corrected. Latent on demo data (all local currency), real on live data.

traced to the stored procedure, line by line

Differs · by decision

Printing & reports

The desktop uses FastReport, whose templates aren't portable to the web. We render clean HTML print views instead — every document and list prints.

documented non-goal · print output verified

Fixed · crash the browser caught

Bank list ordering

The two Banka lists threw a JavaScript error on every render (missing state entry) — invisible to the API tests, only a real browser surfaced it. Fixed and re-verified to zero errors.

caught in the final Playwright walkthrough

Differs · by decision

Payroll calculation

Gross-to-net is a 27,000-line engine tracking yearly Czech tax law. We show the stored payslips read-only; the calc stays on the desktop. A deliberate scope line, not a gap.

assessed in a dedicated discovery spike

Rewritten · one feature, many forms

Filters & codebooks

159 separate filter dialogs and dozens of codebook screens collapse into one generic grid filter and one catalog engine — so ~77 codebooks work with almost no per-form code.

the mechanism that makes the port scale

Fixed · opened the wrong document

Invoice identity

An invoice's key is (type, series, number) — the code used only (series, number), so 40 demo document pairs collided: opening one showed a different document, and edit/delete authorized against the wrong record. The type is now part of the key everywhere.

found in end-to-end testing · 4 bugs fixed in that pass

Fixed · wrong depreciation on disposal

Asset write-off year

Depreciation ignored the disposal date entirely. Now it stops at the disposal year, halves the tax depreciation in that year, and zeros it when acquired and disposed in the same year — per the original's rules.

grounded in the Delphi source, line-referenced · 4 tests

Fixed · rounding drift

Money rounding tie-break

Our rounding split .XX5 ties the wrong way on ~4% of cases versus Delphi's rule (1.025 → 1.02 not 1.03). Rewritten to mirror the original exactly — now 0 divergences over ±2 million test inputs.

the highest-value money fix of the project

Fixed · lookups silently failed

Space-padded keys

The database pads codes with spaces ("CSOB   "). Several lookups compared without trimming, so postcode → city autofill and others silently returned nothing. Trimmed on both sides everywhere.

a whole class of silent-miss bugs, closed

Fixed · usability

Cash-amount input lost focus

Typing an amount in a cash document re-rendered the whole row on every keystroke, stealing the cursor after one digit. Now the total updates in place; the field keeps focus.

small, but it made the form unusable

08 The bottom line

The demo is working, tested, and browser-verified. The core financial engines — the part that's genuinely hard and genuinely risky — are done and proven against the original's own numbers. What's left is a well-understood tail: two big items held back by explicit decisions (payroll calc, admin), and smaller items with no demo data to run on. Nothing shipped is unverified, and nothing is faked — where the data didn't support a real, testable feature, we left an honest placeholder rather than a hollow one.