Loading
ERP

Quoting, orders and invoicing you can bill from

Most home-grown order and invoicing systems have the same defect, and it is nearly always discovered by accident. The totals are worked out in the browser, which means they are worked out somewhere the user can reach — and anything that writes to the line table without going through a form leaves every total downstream quietly wrong.

Build an ERP we can actually bill from.

You are probably here because

  • A total on screen does not match the sum of the lines, and nobody knows when it diverged.
  • An import wrote straight to the line table and no header was recalculated.
  • Invoice and order numbers are typed by hand, or patched by a nightly script.
  • Discounts are applied inconsistently because the rule lives in whoever raised the quote.
  • Finance keeps a parallel spreadsheet to check the system, which rather defeats the point.
  • Nobody can say with confidence that last quarter's figures were arithmetically correct.
  • Partial deliveries and partial invoices are handled by editing the original document.

What is actually going wrong

Derived values computed on the client are not really derived. They are a suggestion the browser makes and the database accepts, and any path into the data that does not go through that browser — an import, an API call, a support fix run directly against the database, a second screen written later — bypasses it entirely.

This is not a rare edge case; it is the normal operation of a growing business. You import a price list. You take orders through an API. Someone corrects a line in the admin panel. Each of those is a moment where a header total can stop matching its lines, and because nothing complains, the error is only found when a customer or an accountant notices.

The related failure is numbering. Order and invoice numbers assigned by counting existing rows, or by a nightly job, will eventually produce a duplicate or a gap under concurrency — and an invoice number is exactly the field where neither is acceptable.

What we build

Derived values are computed on the server, where the user cannot reach them. A calculated field works out a line's net from quantity, price and discount; a rollup sums those lines into the order or invoice header. Both recalculate on every save, evaluate in a defined order so a header total can consume a line's result, and can filter which child rows count — so cancelled lines are excluded by the rule rather than by hoping nobody forgot.

Because it runs server-side, it does not matter how the data arrived. A form, an import, an API call and a custom function all trigger the same recalculation, and a consistency sweep catches anything that got in another way. A formula that fails leaves the previous value alone rather than writing a wrong number, which is the correct behaviour and not the usual one.

On top of that sit the document lifecycle — quote to order to despatch to invoice, with permitted transitions rather than free-form status edits, and line-level provenance so partial fulfilment and partial invoicing do not require editing the original — plus number schemes that allocate atomically, price lists with quantity breaks, and discount rules with explicit stacking control.

How it goes together

  1. 01

    Model documents and lines properly

    Headers and lines as linked datastores, with the relationship explicit rather than implied by a shared reference column. Almost every totals problem in a home-grown system traces back to this being loose.

    Built from
    DatastoresQuery builderRow validation
  2. 02

    Move the arithmetic to the server

    Calculated fields for line-level values, rollups for header totals, with an explicit evaluation order so a total can consume a result computed earlier in the same save. Rollups can filter which child rows count, so cancelled or draft lines are excluded structurally.

    Built from
    Calculated fieldsRollupsAuditing
  3. 03

    Make numbering safe under concurrency

    Number schemes allocate atomically, so two users raising an invoice at the same moment cannot receive the same number, and a failed transaction does not leave a gap that finance has to explain.

    Built from
    Number schemesTransactional documents
  4. 04

    Define the lifecycle as transitions

    Quote to order to despatch to invoice, expressed as permitted transitions rather than an editable status field, with line-level provenance so a partial despatch or partial invoice references the lines it came from instead of mutating the original document.

    Built from
    Transactional documentsWorkflowsElectronic authorisation
  5. 05

    Get pricing rules out of people's heads

    Price lists with quantity breaks, and discount rules with explicit control over what stacks with what. This is usually where the recovered margin is, because inconsistent discounting is rarely deliberate and almost never measured.

    Built from
    Pricing & commissionsReportsDashboards

The platform features doing the work

Nothing here is written specially for this use case — it is the same platform every ActiveManage application is built from. The full feature list is on the platform page.

FeatureWhat it doesWhy it matters here
Calculated fieldsServer-side field arithmetic, recomputed on every save.The value cannot be edited into disagreeing with its inputs, because it is not the user who computes it.
RollupsHeader totals summed from child lines, with filtering over which rows count and a defined evaluation order.Handles the case client-side totals always get wrong: data that arrived without passing through a form.
Consistency sweepA pass that recalculates and catches values that drifted — after imports or direct database writes.The safety net for the paths nobody anticipated, which in a real business is most of them.
Number schemesAtomic allocation of order, invoice and document numbers.No duplicates under concurrency, no gaps to explain to an auditor.
Transactional documentsQuote to order to despatch to invoice, as permitted transitions with line-level provenance.Partial fulfilment stops meaning "edit the original and hope", which is where the audit trail usually dies.
Pricing & commissionsPrice lists with quantity breaks, discount rules with explicit stacking control, margin-based commission.Discounting rules become enforceable rather than cultural.

What you end up with

  • Totals recomputed server-side on every save, whatever wrote the data
  • A consistency sweep that catches imports and direct SQL
  • A failed formula leaves the value alone rather than writing a wrong number
  • Invoice numbers allocated atomically — no duplicates, no gaps
  • Partial despatch and partial invoicing without editing the original
  • Discount and price rules enforced rather than remembered

Whether this is for you

A good fit when

  • Businesses billing from a system they built themselves and no longer entirely trust.
  • Anywhere orders arrive through more than one route — forms, imports, an API, a marketplace.
  • Operations with real pricing complexity: quantity breaks, customer-specific prices, stacked discounts.
  • Anyone whose accountant has started reconciling the system against a spreadsheet.

Probably not, if

  • A business that just needs to raise invoices. Buy accounting software — it is inexpensive, it is good, and this is not that.
  • Anywhere an existing finance system works and the real requirement is getting data into it. That is systems integration, and it is a much smaller job.
  • Full statutory accounting as the primary goal. The ledger is there, but if your requirement is filing rather than operations, start with an accountant.

How a project like this runs

First

The document model and the arithmetic, validated against your existing figures. Reconciling a month of real orders against the old system is the test that matters.

Then

Lifecycle, numbering, pricing rules and the routes data arrives by — usually where the integration work sits.

Handover

Formulas, price lists and discount rules are configuration, so commercial changes do not queue behind a developer.

Questions we get asked

Why does it matter whether totals are calculated on the server?

Because the browser is only one of the ways data reaches your database. Imports, API calls, custom functions and direct fixes all bypass it. Server-side calculation means every one of those paths produces the same, correct total.

What happens if a formula is wrong or fails?

It leaves the existing value alone rather than writing a wrong number. Silently storing a bad figure is far more damaging than declining to update one, particularly on anything you bill from.

We import orders from a marketplace. Will the totals be right?

Yes. Recalculation is triggered by the save, not by the form, so an import recalculates exactly as a user would. The consistency sweep then covers anything that got in by an unanticipated route.

Can it handle partial deliveries and partial invoices?

Yes. The lifecycle is a set of permitted transitions with line-level provenance, so a partial despatch or invoice references the lines it derives from instead of editing the original document.

Do we have to replace our accounting system?

No, and usually you should not. This is the operational side — quotes, orders, despatch, invoicing. There are connections to Xero, QuickBooks, Sage and bank feeds, so the finished figures go where your accountant expects them.

Sound like your week?

Tell us what you are trying to fix and we will tell you whether this is the right shape for it — including when it is not.