Case study · Desktop accounting to web app

TurboCASH 4, desktop accounting, now a web app

We converted the core of TurboCASH 4, open-source Windows accounting software written in Delphi on a Firebird database, into a web app on React, C# and PostgreSQL. We read its UK starter books out of a Firebird 1.5 database with the installer’s own Firebird, wrote its posting rules down from the source, and ran its arithmetic: at 20% VAT, one VAT-inclusive amount in six splits into a net and VAT a penny over the amount typed, which its balance check then refuses. The web version rounds VAT once so it always adds up. A year of demo books balances on every day tested. The conversion took about 50 minutes; it’s independent of TurboCASH’s publishers.

Last updated

Converted Nov 2, 2026About 50 minutes of conversionDelphi + Firebird → React, C#, PostgreSQL

TurboCASH 4 is open-source accounting software for Windows, written in Delphi on a Firebird database and released under the GPL. Small businesses have kept their books in it for years. We moved its core to the web: the chart of accounts, journals, VAT, invoices, stock and the reports, with its posting rules.

Open the web versionThe original

An independent conversion of the GPL version 4, not made or endorsed by TurboCASH’s publishers.

176,525 linesof Delphi read: 207 units and 181 forms
74 accountsread from its own Firebird books
1 in 6VAT-inclusive amounts at 20% a penny over, by its own arithmetic
24 testsposting rules, a year of books, the database
The brief

Accounting software, in a browser

Our first conversion was a small invoicing program. This time we wanted something bigger and stricter: double-entry accounting, where every posting must balance and a penny matters. TurboCASH 4 fits. It’s a real, long-lived product, written in Delphi on a Firebird database, and its source is public under the GPL version 2 or later, so we can show every step.

Challenge

The books are in a Firebird 1.5 database no current server opens, the source download is damaged, and the program wouldn’t start on our Mac.

Approach

Read the books with the installer’s own Firebird, read the posting code, run its arithmetic, write the rules down, then build.

Result

A web app on our standard stack with TurboCASH 4’s own UK books and rules, VAT that always adds up, and a year of demo books that balance.

Before and after. The old program kept each set of books in a Firebird database on the PC; the web version keeps them in PostgreSQL behind an API.
In the desktop programIn the web app
One Firebird database (books.FDB) per set of booksPostgreSQL, one workspace per set of books
Posting rules in LedgerRoutines.pas (4,558 lines)One C# posting engine, checked by the API on every change
Unposted batches in per-user tables (BAT0T…)Unposted batches saved as drafts until they post
Running totals per account and period (TOTALS)Balances worked out from the posted entries
Batch entry grid: F5 Balance, F6 Post, F7 inclusiveThe same grid, the same keys
User switches for Batch entry and Update ledgerThe same rights, checked on the server
A report designer and printed reportsFixed reports that print or save as PDF
Installed on each Windows PCOne server, any browser, phones included
Step 1

Get the books out

On this conversion

TurboCASH keeps each set of books in a Firebird database file. The UK starter books that come with version 4 are in Firebird 1.5’s format, which today’s Firebird can’t open. The installer brings its own Firebird 2.1, and that one can. On a Mac it ran under Wine, even though TurboCASH itself stopped at start-up there.

The starter books hold a chart of 74 accounts, four VAT rates, eleven journal types and the periods, and no transactions: a set of books to begin with. A short script reads them into a file the web version loads, so the server needs no Firebird at all.

On your app
Terminal · reading the old books
$ xxd -s 0x12 -l 2 books.FDB
00000012: 0a00                 # on-disk structure 10: Firebird 1.5

# Firebird 2.1, from TurboCASH's own installer, run under Wine:
$ wine isql.exe -u SYSDBA localhost:C:\work\uk.fdb
SQL> SELECT COUNT(*) FROM ACCOUNT;      -- 75 (74 and an empty one)
SQL> SELECT COUNT(*) FROM TRANSACT;     -- 0: starter books, no transactions

$ node tools/extract-books.mjs books.FDB Samples/en-uk.json
en-uk.json: 74 accounts, 4 VAT rates, 11 journal types, 29 periods

Old accounting software usually keeps its data in a real database: Firebird, Paradox, Access, an old SQL Server. If no current server opens it, the program’s own installer often brings one that does. Get the chart of accounts and the settings out first; everything else stands on them.

Step 2

Read the posting code and write the rules down

On this conversion

The source on SourceForge for this exact version is a damaged zip: 404 files came out of it, the core included. Nearly every rule that matters is in one unit, LedgerRoutines.pas: what a journal line becomes when it’s balanced, what’s checked before it posts, how a document becomes ledger entries, and how stock and its average cost move. In plain words:

  1. Nothing posts to the debtors or creditors control account, to a main account with sub-accounts, or to an inactive account.
  2. A date must fall in an open period of this year or last year, and last year only while posting to it is allowed.
  3. A batch must balance in every period, to the penny, before anything is written.
  4. In a cash book the line’s own account takes the net amount and the VAT, and the bank takes the whole amount. In other journals the line’s account takes the whole amount and the contra the net.
  5. VAT can’t go on a debtor, creditor, bank or tax account.
  6. An invoice posts the customer for the whole amount, each line’s sales account for the net and the VAT account for the VAT. A purchase does the same with the supplier and the stock account.
  7. With cost of sales on, each stock item sold moves its average cost from stock to cost of sales.
  8. A purchase updates the average cost: with nothing on hand it becomes the purchase price; otherwise it’s weighted by what’s on hand.
  9. Income and expense accounts start each year at nil; last year’s result goes to retained income.
  10. Quotes and orders never reach the ledger, and a posted document can’t change.
On your app

In accounting software, the screens are the easy part. The rules about what may post, and where, are what the bookkeeper and the accountant rely on. Write them down and have someone who does the books read them before anything is built.

Step 3

Run the old arithmetic

On this conversion

Reading the balancing code, one thing stood out: the net amount and the VAT of a VAT-inclusive line are rounded separately. So we re-created that arithmetic and ran it on every amount from 0.01 to 1,000.00. At 20%, 16,667 of the 100,000 come out a penny over what was typed. At 5% and 15%, none do.

£12.15 with 20% VAT: £10.13 + £2.03.

The balance check allows no difference, so by the code such a batch can’t post. We found this in the code and proved it by running the arithmetic; we didn’t watch the program refuse a batch.

On your app
C# · the original arithmetic, re-created
// LrBalanceBatch (LedgerRoutines.pas), a VAT-inclusive line, re-created in C#:
// Rate = 1 + percent / 100; net and VAT are rounded on their own (RoundAmount).
public static (double Net, double Vat) InclusiveSplit(double total, double percent)
{
    var rate = 1 + percent / 100;
    var excTotal = total / rate;
    return (RoundAmount(total / rate), RoundAmount(Math.Abs(excTotal) * (rate - 1)));
}
// InclusiveSplit(12.15, 20) == (10.13, 2.03): 12.16, a penny over.
C# · the web version
// The web version: round the VAT once; the net is what's left.
public static (decimal Net, decimal Vat, decimal Gross) Split(decimal amount, decimal rate, bool inclusive)
{
    amount = Pence(amount);
    if (inclusive)
    {
        var vat = Pence(amount * rate / (100 + rate));
        return (amount - vat, vat, amount);     // 12.15 -> 10.12 + 2.03
    }
    var v = Pence(amount * rate / 100);
    return (amount, v, amount + v);
}

A rounding rule always looks reasonable on the page. Run it against every amount a business might type and you see how often it goes wrong. With VAT, round once and let the other part be what’s left.

Step 4

Decide what to fix, and what to keep

On this conversion

Reading every rule turns up things nobody asked about. None of these lose money, but each one decides what a bookkeeper sees, so each has a decision.

On your app
FoundWhat TurboCASH 4 doesWhat we did
VAT-inclusive amounts a penny overBalancing a journal line, LrBalanceBatch works out the net as Total / Rate and the VAT as net × (Rate − 1), and rounds each on its own. At 20%, 16,667 of the 100,000 amounts from 0.01 to 1,000.00 come out a penny over: 12.15 becomes 10.13 + 2.03. Its balance check, DoesBatchBalance, allows no difference. Found in the code; we didn’t see it in the running program.Changed: the VAT is rounded once and the net is what’s left, so they always add up. At 5% and 15% the two give the same result.
No credit limit warning for customersThe invoice screen warns when an account is over its credit limit only for a supplier, though the message talks about the debtor’s balance. For a customer it shows the amount available and nothing more.Changed: an invoice or order that takes a customer over their limit says so before it’s saved.
Dates before the books slip throughValidateBatch checks that a date isn’t after this year, but the check for dates before last year is commented out.Fixed: a date outside this year and last year is refused, with the range.
A VAT account that doesn’t existIn the UK starter books, both starter stock items point their input VAT at account 48, which isn’t in those books.Fixed on import, and the import says so.
Cost of sales counted as incomeThe UK starter books put Cost of Sales (100-000) in the income group, so the income statement shows income after cost of sales.Kept as the books have it, and labelled “income after cost of sales”.
One customer entry per invoice linePosting an invoice, the original debits the customer line by line.Changed: one entry per document, so a payment is allocated against the invoice as a whole.

In accounting, a change to a total is never small, even a penny. List each one with what the old program did, and let the owner and their accountant decide before the switch.

Step 5

Build it on a standard stack

On this conversion

The web version runs on the same stack as this site: React and TypeScript screens, a C# API on ASP.NET Core and a PostgreSQL database. Posting happens in one place on the server. The screen asks it what a document or batch will post, and shows the entries before anything is written.

It keeps what TurboCASH users know: the account codes and journal names, Update ledger as its own step, the batch grid with F5 to balance and F6 to post, and the two user rights for entering and posting. It adds a start screen with sales, profit, bank, debtors and VAT, a ledger preview on every invoice, a log of every change, and a phone layout.

On your app
  • Keep the words bookkeepers know: debtors, creditors, contra, Update ledger. Renaming them costs more than it gains.
  • Post in one place on the server. A rule in the screen can be skipped; a rule in two places will drift.
  • Show what will post before it posts. In the old program you balanced a batch to see it; here the entries are always on the screen.
  • Watch for what doesn’t move easily: report designers, bank imports, plug-ins, multi-currency. We left those out of this demonstration and listed them.
Step 6

Test it like the books

On this conversion

24 automated tests run on every deploy: the VAT split on 100,000 amounts at four rates, the original’s penny, each posting rule, and a whole demo company built from the start of last year to the day it runs, whose trial balance, balance sheet, control accounts and age analysis must agree on four different days. Then a browser went through it as a bookkeeper would, at desktop and phone size, under this site’s security policy.

On your app
Terminal · the test run
$ dotnet test
  RulesTests      15 passed   VAT splits, the penny, cash books, control accounts,
                              periods, invoices, average cost, reversals
  DemoDataTests    6 passed   a year of books balances on four different days
  StoreTests       3 passed   the clerk enters, the owner posts, in PostgreSQL
Passed!  Failed: 0, Passed: 24

For accounting software, the strongest test is a whole set of books: post a year of ordinary work through the new rules and check that every report agrees with every other.

The clock

How long it took

Claude Code did the work on Nov 2, 2026, with Jan choosing the program and the scope. The times come from the session’s clock and the files’ timestamps, in Pacific time. About 50 minutes from the books to the commit; trying the original under Wine came before, and this page and the deploy after.

WorkTimeWhat came out of it
Install the original under Wine on a Mac19:25–19:36Installed; the program itself stopped at start-up, so its screens come from a Windows PC
Read the books and the source20:05–20:16Firebird read through the installer’s own server; source unpacked; the starter books extracted; the penny found
Posting engine, database, API and 24 tests20:16–20:30The demo company’s books balance on every day tested
React screens20:30–20:46Documents, Update ledger, batch entry, debtors, creditors, stock, ledger, reports, setup
Browser walkthrough and fixes20:45–20:51Desktop and phone; layout and labelling fixes
README and commit20:52Its own repository and license
Deploy21:20Its own service, database and web address; every smoke test at 200

This is the core of TurboCASH, not all of it: no point of sale, multi-currency, budgets, projects, bank import or report designer. A real conversion of a program like this takes longer, and most of the extra time goes to steps 2 and 4: the rules, and the decisions about what you find.

Lessons

What we’d tell anyone moving accounting software

  1. Read the posting code before the screens.In accounting software the rules that matter are in a few long routines. Here one unit held nearly all of them.
  2. Get the books out first.A database a current server can’t open is still readable with the program’s own tools. Once the chart of accounts was out, everything had something real to stand on.
  3. Run the old arithmetic, not just read it.A rounding rule looks fine on the page. Run against 100,000 amounts, it shows how often it goes wrong.
  4. Say what you checked and how.The penny was found in the code and proved by running its arithmetic, not by watching the program refuse a batch. The page says exactly that.
  5. Check the license, and who still sells it.TurboCASH 4 is GPL, so the web version is too, in its own repository. Its publishers still sell a later version, so this page says plainly that it’s independent.
Your program

Still keeping the books in an old desktop program?

If your business, or your clients, depend on accounting or invoicing software written years ago, in Delphi, Visual Basic, Access or FoxPro, we can look at it with you. Send what you know; the first 30-minute call is free.

  • What the program does, and how many people use it each day
  • What it’s written in, if you know, and whether you have the source code
  • Where its data lives: Firebird, Access, SQL Server, a folder of files
  • What it connects to: a bank, a till, a printer, another program
Try it

Open the books

The web version opens on Fernley Joinery Ltd, a made-up UK joinery workshop on TurboCASH 4’s own UK chart of accounts, with last year and this year posted. Your copy is yours alone and is deleted after 48 idle hours. Post the two waiting invoices from Update ledger, type £12.15 with VAT into the sales journal and press F5, read the trial balance, or switch to Tom, the clerk, who can enter batches but not post them. Start over from TurboCASH’s empty starter books if you’d rather begin from nothing.

Open the web versionTurboCASH on SourceForge

TurboCASH 4 is released by its authors under the GNU General Public License, version 2 or any later version. The web version is an independent modified version under the same license, not made, supported or endorsed by TurboCASH’s publishers.