Featured Work

Reworking Client Numbering to Support Alphanumeric IDs, End to End

An enterprise client running SAP alongside TEAMBOX needed matching client codes in both systems — a change that touches nearly everything client numbering ever touches, including an architecture correction made mid-build.

July 2026 · In progress · ~69 commits

Company not where the ID lives Client A External ID lives here Client B External ID lives here One company, more than one client relationship — each needs its own ID

Started on Company, mid-build. Moved to Client once the domain model made the actual shape of the relationship clear.

The setup

An enterprise client running SAP alongside TEAMBOX needed to use the same alphanumeric client codes in both systems. That sounds small until you realize TEAMBOX's client numbering had always quietly assumed a purely numeric ID — an assumption baked in years ago that had simply never been tested against a real alphanumeric requirement, because nobody had needed one, until now.

An architecture correction made mid-build, not before it

The new external-ID field started life on the Company record — the natural-seeming place for an identifier tied to a client relationship. Partway through the build, the domain model made it clear that was the wrong home: numbering is fundamentally a client-level concern, and a single company can have more than one client relationship under it. Moved the field from Company to Client mid-build rather than shipping the wrong owner and fixing it later — the kind of correction that's cheap while only one piece of code depends on where a field lives, and considerably more expensive once several do.

Decoupling numbering from payment references

TEAMBOX's project numbering and its ESR/QR/DATEV/ABACUS payment references had always assumed the same underlying numeric format. Decoupling them meant building a per-client job-number pattern engine that generates project numbers independently of whatever format the new external ID happens to take — so a client's payment references keep working exactly as they did before, regardless of what their client code looks like now.

The external ID itself is immutable once set, to guarantee uniqueness. Once assigned, it can't drift — which matters considerably more once a second system, the client's own SAP instance, is relying on it staying exactly matched.

Threading it through two frontends, and catching its own regressions

The new field touches search, filtering, and column display across five separate UI surfaces spanning both TEAMBOX's legacy ExtJS frontend and its newer Angular one — each shipped behind a feature flag, with REST API exposure and a permanent Playwright end-to-end suite covering the new behavior.

Two regressions surfaced and got fixed in review before they reached anyone else. A literal external ID of "0" was being silently treated as unset — the classic falsy-string trap in a language that doesn't automatically distinguish "empty" from "the string zero" at every layer it needs to. And client search broke outright the moment IDs stopped being purely numeric, because parts of the existing search implementation had quietly assumed a numeric-only field the whole time, with nothing ever having tested that assumption until it was no longer true.

Where it stands

Shipped behind a feature flag, in review as of this writing — not the finished story yet. But far enough along that the interesting failure modes, the ones that only exist once alphanumeric IDs are actually present somewhere in the system, have already surfaced and been fixed in review, rather than waiting to be found by a client in production.

Feature Data Model Feature Flag e2e Testing