· By Sajeevan (Saj) Veeriah
Engineering case study · 3 min read
Making catalogue repricing reviewable at SWL
A local-first pricing workflow with deterministic matching, exact money handling and an operator-reviewed ServiceM8 export.

Stan Wootton Locksmiths needs to reprice a ServiceM8 materials catalogue using supplier exports. A spreadsheet can perform the arithmetic, but the harder problems are preserving identifiers, matching the right items and ensuring that someone reviews the changes before import.
I developed a local-first application spanning requirements, pricing rules, desktop and browser builds, testing and release packaging. I treated the import file as a controlled output of a review process.
The rules shaped the software
The application compares an untouched supplier export with the current materials list and applies the confirmed 30 percent markup to GST-exclusive cost. It produces a ServiceM8-format import alongside change, exception, rollback and audit reports.
An item absent from a supplier file is not automatically deleted. Matching proceeds from an exact normalised code to an operator-approved alias. Description similarity is a suggestion for review, not authority to overwrite an item.
Sources: [1]
One domain model, several application surfaces
I used a shared React and TypeScript interface over pure domain modules for money, pricing, comparison, mapping and output. A typed platform adapter connects that logic to the selected runtime.
| Surface | Responsibility |
|---|---|
| Windows desktop | Tauri commands and a Rust backend with bundled SQLite. |
| Local browser | A loopback Node server for local web use. |
| Static demonstration | A session-only store for demonstrating the workflow. |
| Shared domain | Deterministic matching, exact money handling and export rules. |
This separation allowed the business rules to remain consistent while the desktop and browser surfaces handled files differently. Imported business rows stay in memory rather than being persisted.
Making uncertainty visible to the operator
A failed match should become an exception the operator can examine. It should not silently become a guessed product association. The change and rollback outputs make the proposed import inspectable and give the workflow a recovery path.
Exact money handling was another deliberate boundary. Binary floating-point arithmetic is not used for money in the pricing domain. The output also needs to preserve item codes and barcodes as identifiers rather than treating them as convenient numeric values.
Sources: [1]
Checking the contract as well as the interface
The project record documents unit and property-based tests, browser checks, accessibility runs, installed-desktop tests and Rust unit tests. A byte-for-byte round trip checks the ServiceM8 CSV contract. Type checking, linting, testing and packaging are part of CI.
This article summarises that established test strategy; it does not present a fresh execution of the application test suite. I am not claiming a measured time saving, revenue gain or error-reduction percentage without an operational dataset.
Sources: [1]
The wider engineering lesson
The important design decision was to give uncertainty somewhere explicit to go. A pricing tool needs a clear relationship between an input, a rule, an operator decision and an output. That principle also applies to automation and AI systems where a plausible result should remain open to inspection.
A future evaluation could compare reviewed runs using reconciliation outcomes, exception categories and operator effort. That would measure practical usefulness without confusing test coverage with a demonstrated business outcome.
Sources and further reading
Engineering case study based on the public project record. Client data, private implementation details and unsupported business metrics are omitted.