Fire-safety inspection and servicing contractor, 3-4 person office

Field Service ERP for a Fire-Safety Inspection Contractor: Paper Books to a 42,000-File Digital Archive

Carbon-copy paper work-order books in triplicate, group-chat dispatch with no record of who accepted a job, Excel and Word templates re-typed by hand for every invoice and quote, and an accounts-receivable spreadsheet north of $1.7M across roughly 490 rows with duplicate and hidden rows that even the client's own staff couldn't fully trust.

What Was Built

A full call-to-payment field service system built on an open-source ERP platform: digital work orders on technicians' own phones, quoting and scheduling, one-click invoice PDFs with email delivery, a three-role permission model enforced at the database layer, a 42,000-file legacy document archive migration, a verified legacy accounts-receivable import, recurring-contract billing, and flag-only GPS auditing.

What's Provable Today

The client signed off on the end-to-end flow after a live demo, then came back unprompted asking for more automation. The build itself is backed by roughly 2,400 automated tests across 147 files, a race-tested invoice numbering scheme, an audited legacy AR import, and rehearsed full-restore backup drills. No time-saved or error-reduction figures were measured, and none are claimed here.

By Serg Litt

What the paper actually looked like

The client ran a fire-protection inspection and servicing business out of a 3-4 person office, entirely on paper, phone calls, and spreadsheet filing. Not “mostly digital with some paper forms”, genuinely paper-first, end to end.

A job started with office staff writing a job number by hand from a pre-numbered work-order book bought from a commercial forms printer, then filling in the customer, technician, and problem details before handing a physical copy to the technician on their way out the door. Every paper work order produced three physical copies from a carbon-copy book: one for the customer, one for the office, one for the technician as a pay record.

On site, the technician filled in the rest of the same paper form by hand: arrival and departure times, break and travel time, hours split by pay-rate class across up to two technicians on a job, a checklist (inform the monitoring agency, disable the system before work, which keys are needed and where), the work performed, materials used, and a customer signature. The office copy came back later as a photograph or a scan, and someone retyped it. The original project plan even called for an OCR-assisted transcription step to make that retyping less painful, a step that was dropped entirely once the team decided the honest fix was to stop generating paper in the first place, not to build tooling to read it faster.

Dispatch ran over group chat. There was no record inside any system of who was offered a job, who accepted it, or when.

Invoices came from an Excel template, one per job, typed up by office staff after transcription and numbered by hand. Quotes came from a Word template with boilerplate scope-of-work paragraphs, assembled per client and site, also by hand. Neither numbering scheme was a designed system. A full historical sweep found invoice numbers had climbed into the 5,500s by late 2025, then restarted in the 2000s for 2026. Quotes peaked in the 6,000s in 2025, and 2026 was running three separate numbering blocks at the same time.

The receivables spreadsheet nobody could fully trust

Accounts receivable lived in two hand-maintained Excel workbooks, not a ledger. An independent audit re-derived every figure from the raw files, five separate times, to be sure the numbers held up. What it found:

  • Outstanding invoices totalled north of $1.7 million across roughly 490 rows, once two confirmed duplicate rows were removed.
  • Invoice numbers weren’t a reliable key at all. Numbers were reused across genuinely different invoices within the same year’s sheet, and two historical sheets shared over a hundred numbers with almost none of them referring to the same actual document. The real identity of an old invoice had to be reconstructed from number, site, and amount together, never the number alone.
  • A meaningful slice of the book, worth tens of thousands of dollars, was hidden in the spreadsheet and silently included in every total while invisible on screen, because the sheet’s autofilter range had gone stale relative to its own data.
  • Two dozen invoices appeared as both outstanding and paid at once, in some cases with contradicting records: one invoice carried a partial-payment note for one amount while the payments sheet recorded two separate cheques totalling a different, larger figure, flagged by the client’s own staff as “get back to this” and never resolved.
  • Roughly two-thirds of rows had no reliable bill-to entity recorded at all, only a job-site address, which isn’t always who actually gets billed.
  • A meaningful share of the outstanding book was more than 90 days overdue, and a single client relationship accounted for a disproportionate share of the entire outstanding total.

That’s the reality “just use a spreadsheet” produces once a business has been running on one for long enough. Nobody set out to build an unreliable ledger. It accreted, row by row, over years, until the row count and the reuse of invoice numbers made it genuinely impossible to trust at a glance.

What got built

A full field-service operations system was built on top of an open-source ERP platform, covering the entire job lifecycle end to end, in the client’s own vocabulary rather than a generic software vendor’s terms.

Intake and quoting. Office staff take a call and create a permanent job record: customer, billing and service address, contact, problem description, urgency, access instructions, and any customer reference number. A structured quote screen mirrors the client’s own paper quote layout: scope-of-work line items, truck-charge handling, payment terms, signature capture, and the quote number survives into the resulting job and invoice as “As per quote #,” matching how the client already referred to their own paperwork.

Scheduling and dispatch, replacing the group chat entirely. Jobs are assigned directly to a technician, reschedule reasons are kept in the job’s history, and arrival times are modelled as a window rather than a single point in time, because that’s how the business actually promises appointments to customers.

Fully digital work orders, the single biggest change from the old process. The photograph-and-OCR pipeline from the original plan was dropped. Instead, the technician completes the entire work order on their own phone, on site: clock in and out with GPS captured when available (never blocking if it isn’t), the same checklist that used to be on paper, a work-performed description, materials, an optional customer signature and printed name, and a completion photo. Twenty-eight distinct fields on the old paper form were mapped one by one; all but two carried across to the digital system directly or better, the other two having legitimately merged into a single system-assigned job number once the two-book paper system stopped existing.

One-click invoicing. A completed, verified job generates an immutable PDF invoice, pulling billing information from the accepted quote and calculating tax automatically, emailed directly from the system with delivery status tracked per invoice. Payments are recorded and reconciled against each invoice, and a job only closes once it’s paid in full. One job maps to exactly one final invoice, enforced at the database level with a validation hook and a unique index, not just a convention staff are trusted to follow.

A recurring/annual contract billing engine, supporting monthly and quarterly maintenance contracts, which is exactly the cadence a fire-inspection business runs on. It was built, then deliberately held back from the interface until the client actually asked for it in writing, rather than shipped speculatively.

Flag-only GPS auditing. The system never blocks a clock-in or clock-out that looks physically implausible. It surfaces the flag for office review instead. That’s a considered trust-versus-verification design choice, not a missing feature, the same principle shows up again in how the permission model treats staff, below.

The three-role permission model

Three roles exist, with hard boundaries enforced at the permission layer, not just hidden in the interface:

  • Admin sees everything, including money.
  • Coordinator/office handles intake, scheduling, and quotes, and is structurally blocked from ever seeing invoices or payments, not hidden from a menu, blocked at the API.
  • Technician is mobile-only, sees only their own assigned jobs, and loses access to a job’s data the moment it’s invoiced.

Those boundaries were verified with direct-API denial testing: hitting the API directly as a technician or coordinator and confirming an HTTP 403 with no data leaked in the response, not just confirming the button was missing from a screen.

The 42,000-file archive and the legacy AR import

Two migrations ran alongside the new system, both because “start fresh, ignore the old records” wasn’t an acceptable answer for a business with years of client history.

A per-client document archive imported roughly 42,000 legacy files, invoices, quotes, reports, certificates, correspondence, from the client’s old file storage, organized by client, document type, and year, using the client’s own filing language rather than generic file names. The goal was a browsable client history, not a generic document dump.

The legacy accounts-receivable import brought the historical invoices and payments from the two Excel workbooks into the new system as real, ledger-affecting financial documents, not just reference data sitting off to the side. Every data-quality defect found in the audit above, the duplicate rows, the reused invoice numbers, the hidden rows, the invoices marked both paid and outstanding, was resolved by an explicit decision from the business owner, never a silent guess. That “ambiguity creates a question for a human, never a silent assumption” rule ran through the whole import, and through the rest of the build.

What’s deliberately not claimed

This section exists because it would be easy, and dishonest, to round “the client signed off after a demo” up into a results claim. Here’s the honest line.

Evidenced: the client signed off on the end-to-end call-to-payment flow after a live walkthrough demo, with only minor punch-list items remaining, not a rebuild request. The system went live on real production data, not a pilot, after a formal go-live checklist covering data cleanup, credential posture, deploy verification, backup and disaster-recovery proof, and a staged rollout of live email sending. The client came back afterward, unprompted, asking for more, specifically to expand the recurring-contract scheduling and to build a report-regeneration feature so office staff could turn inspection reports around faster for their own clients. An unprompted ask for more automation is a stronger signal of real adoption than a testimonial, because nobody had to solicit it.

Not evidenced, and not claimed: no time-saved figure, per invoice, per work order, or per week of office admin. No measured reduction in billing errors or disputes. No measured improvement in payment collection speed or cash flow. All three are plausible, given how much of the old process involved manual retyping and an accounts-receivable book with duplicate and hidden rows in it, but plausible isn’t measured, and none of those numbers were ever collected. If a business owner is asking what changes are worth to them in real minutes or real dollars, that number has to come from watching the business run on the new system for a while, not from a case study about the build.

The security conversation, honestly

Partway through the project, the business owner raised a real, specific fear: that a staff member could walk out with the company’s data the way it had once been possible to copy an entire shared folder off the old file storage in a single click. The owner wanted a system where nobody could download the app or bulk-extract information from it.

The honest answer given back was not a promise of an unbreakable system, because no such promise would have been true. The new system already required drilling into one document at a time rather than a one-click bulk copy, a real, structural difference from the old shared-drive setup, not a marketing claim. On top of that, the team offered a concrete, non-theatrical addition: rate-limiting how many documents any one staff member could open per hour, with an automatic alert if that limit was exceeded. And the team was explicit that no system, custom or off-the-shelf, can make someone photographing their own screen impossible. The honest goal was deterrence and an audit trail, not an absolute guarantee, and that limit was stated plainly rather than glossed over.

What makes this exchange worth more than a testimonial is what happened next. During a follow-up audit prompted by that conversation, the team checked the “by design” permission claim against the actual configuration rather than letting it stand unverified, and found two real gaps between what was claimed and what was actually enforced. Both were fixed. A vendor willing to audit its own security claim, find it wanting, and say so, is a stronger signal than a vendor who simply asserts the system is secure and moves on.

The same instinct showed up in smaller decisions elsewhere. When the owner asked for hourly backups instead of daily, the team held to a daily cadence with a documented reason, and left the door open to revisit if asked again, pushing back on a request with reasoning, rather than either complying automatically or refusing outright. And when a standalone-invoice feature that had just been merged into the codebase directly contradicted the owner’s repeated, explicit rule that every invoice traces back to a real job or quote, the team flagged the contradiction for an owner decision instead of quietly shipping it and hoping nobody noticed.

Hard numbers

  • 28 fields mapped from the old paper work order, all but two carried across one-to-one or better.
  • 10 fields on the old paper invoice template, all covered, including the exact original remittance wording restored on the client’s request.
  • 14 fields on the old paper quote template, all covered.
  • Roughly 42,000 legacy files migrated into a per-client, per-year document archive.
  • Roughly $1.7 million in outstanding legacy invoices, across roughly 490 rows, imported as real ledger documents after a five-pass adversarial verification re-derived every figure from source before import.
  • Invoice numbers are sequential, unique, and race-tested to be safely allocated under concurrent finalization, never reused, even across a cancelled invoice.
  • Roughly 2,400 automated test functions across 147 test files, covering permissions, invoice numbering, visit ownership, and data round-trips.
  • One fully automated, unattended smoke-test sweep of the live site’s routes runs before every production release, and blocks the release if it fails.
  • Nightly on-host backups plus a separate off-host disaster-recovery copy, both with a rehearsed full restore, not just backups that are assumed to work.
  • Staging-first deployment: every change ships to a separate staging environment and is verified there before it touches production, behind a deliberate, named approval step.
  • Public access to the system is geographically restricted at two independent layers, on top of the usual network protections, reflecting a real client concern about who could reach the system at all.
  • Technicians install the mobile app directly to their Android home screen as a browser-based PWA, no app store, no native build pipeline to maintain.

Why this wasn’t an off-the-shelf product

A 3-4 person fire-inspection office is exactly the size of business generic field-service software is built to serve, and for many shops that’s the right call. This project went custom for reasons specific to this business, not as a default preference for building over buying: the client’s own paper forms, quote language, and numbering habits became the system’s actual data model, instead of the business being bent to fit a generic product’s fields. The three-role permission boundary, coordinator structurally blocked from ever seeing money, isn’t a standard toggle in most off-the-shelf tools. Neither is a 42,000-file legacy archive organized in the client’s own filing language, or a legacy accounts-receivable import that treats years of messy history as something to reconcile rather than discard.

None of that makes custom the right answer for every shop this size. It made sense here because the business had enough operational history, and enough specific process quirks, that fitting it into someone else’s software would have meant losing detail the owner actually cared about.

Want the same kind of build for your shop?

Book the assessment. We will walk your actual paper trail and tell you plainly what is worth automating.

Book Your Free Assessment
Call Now: 647.479.8770Text Serg Direct
Book Your Free Assessment