Case study · Trade-finance ERP

Rebuilding a trading business's
core system, from the studs up.

A dairy-commodity export and trade-finance firm ran its entire operation — deals, purchase orders, shipments, inventory, invoicing and accounting — on a fragile, fifteen-year-old codebase held together by copied files. We replaced it with a modern, fully tested platform, delivered by a two-person team in about eleven months by putting AI at the center of how we work.

Industry
Commodity export & trade finance
Engagement
Full legacy replacement
Team
2 engineers
Timeline
~11 months to production scope
0 → 378
Automated tests
None in the legacy system
2
Engineers on the build
No expansion of the team
~124k
Lines in the new platform
TypeScript + PHP
~11 mo
To production scope
From an empty repo
The starting point

A system nobody could safely change

The business it ran was genuinely complex: international dairy deals with multi-currency pricing, foreign-exchange hedging, export-credit coverage, shipment logistics, and a long tail of generated trade documents — commercial invoices, certificates of origin, certificates of analysis, packing lists. All of it lived in roughly 58,000 lines of hand-written procedural PHP with no framework, no router, and no separation between database code, business rules and HTML.

The deeper problem wasn't the size — it was that the code had become dangerous to touch. A few markers of where it stood:

  • Zero automated tests. Every change was verified by hand, if at all. Files literally named test.php, test2.php and deal_test.php were scratch pages, not a test suite.
  • Versioning by copy-paste. Instead of git history, the team tracked changes by duplicating files — config_bkp.php, export_deal - Copy.php, and a backup/ folder full of date-stamped snapshots. The entire repository was a single squashed commit.
  • Production credentials in plain text. The live database password and third-party SFTP credentials were hard-coded directly into source files, repeated across the PHP app and every report script.
  • Every query hand-built from strings. ~760 raw SQL calls, none of them parameterized — user input flowed straight into queries, a textbook SQL-injection exposure across the whole application.
  • Three runtimes, one tangled database. A PHP web app on Windows/IIS, a Python/Flask report server, and a set of AWS Lambda functions all read and wrote the same SQL Server database directly, with no shared boundary — the team's own README admitted parts of it were no longer fully understood.
What we built

One coherent, tested platform

We rebuilt the system as a single modern application: Laravel 12 and PHP 8 on the backend, a React and TypeScript front end over Inertia, and PostgreSQL in place of the old SQL Server. The three disconnected runtimes collapsed into one codebase with clear internal boundaries — a service layer per domain, typed models and enums, background jobs, role-based access control, and full audit trails on the records that matter.

  • The full domain, modeled properly. Deals, purchase orders, shipments and vessels, inventory with stock movements, multi-currency invoicing, prepayments, factoring, and a credit-limit approval workflow — 77 typed models where there had been none.
  • Live accounting integration. A first-class QuickBooks Online integration syncs bills, invoices and inventory adjustments and ingests payment webhooks — replacing manual re-keying between systems.
  • 378 automated tests and a real CI pipeline. Every pull request runs the suite, linting and type checks against a real database before it can merge.
  • A safe migration path off the old data. We built dedicated import tooling that pulls deals, purchase orders, sales confirmations and payments out of the legacy database into the new schema — the bridge that let the business actually move.
  • Secrets and access done right. Credentials moved to environment configuration, queries went through the ORM, and access is enforced by middleware and permissions rather than hand-rolled session flags.
Before & after
 Legacy systemNew platform
StackProcedural PHP, no frameworkLaravel 12 · React · TypeScript
DatabaseSQL Server (Windows/IIS)PostgreSQL
Runtimes3 disconnected (PHP + Flask + Lambda)1 unified codebase
Automated testsNone378, gated in CI
Data access~760 raw string-built queriesTyped ORM, parameterized
SecretsHard-coded in sourceEnvironment configuration
Change historyCopied files & backupsFull git history + CI
AccountingManual re-keyingLive QuickBooks sync
How two people did it

AI as the multiplier, not the gimmick

A rebuild of this scope — a complete trading ERP with live accounting integration — is conventionally a team-of-five, eighteen-to-twenty-four-month project. Two engineers delivered it in roughly eleven months because AI was woven through the entire workflow, not bolted on at the end.

~60–70%
of the code was AI-generated — our informed estimate. It's a floor-and-ceiling read of the evidence, not a precise measurement.48 commits carry an explicit Claude co-author trailer, but that only counts one tool on one developer's machine. Day-to-day work ran through Claude Code, Cursor and Warp with shared agent guidelines — most AI-assisted work is never tagged. Two engineers producing ~124k lines plus 378 tests in eleven months sits well above an unaided baseline.

Concretely, AI did the work that usually needs more hands:

  • Reading the legacy system for us. Agents traced what the old procedural PHP actually did — the parts even the original team had lost track of — and turned it into a clean domain model.
  • Generating the migration bridge. The field-by-field mapping from the old database to the new schema, and the import commands that move real data, were AI-built and captured as a reusable, checklist-gated runbook.
  • Writing tests alongside features. Testing was an agent obligation, not an afterthought — which is how a two-person team ended up with 378 tests instead of the legacy system's zero.
  • Enforcing standards automatically. Shared coding guidelines, linting and formatting were built into the agent workflow, so quality stayed consistent without a large team reviewing every line.

This is what we mean by software that builds software: the how is our edge, and it compounds. The same leverage that let two people replace a fifteen-year-old system is what we bring to every engagement.

The impact

Faster, cheaper, and finally safe to change

The business moved off a system that was a liability — un-testable, un-auditable, with live secrets sitting in source control — onto one that can be extended with confidence. The delivery economics tell the rest of the story.

~3×
Smaller team than a conventional build
Estimate: 2 engineers vs. a typical 5–6 for a system of this scope.
The calendar time
Estimate: ~11 months vs. an 18–24 month conventional timeline.
0 → CI
From no safety net to gated releases
378 tests, linting and type checks on every change.

Team-size and timeline comparisons are informed estimates based on the delivered scope (~124k lines, 77 domain models, live accounting integration), not a controlled measurement. Repository figures — tests, lines, timeline, commits — are drawn directly from the codebases.

Have a system like this holding you back?

Whether it's a legacy rebuild or something that doesn't exist yet, we'd like to hear about it. Thirty minutes with the team is enough to show you how fast it can be real.