WIP Risk Monitor
Turning unbilled work into an actionable risk queue
Instead of another report showing how much WIP exists, I built a working prototype that helps a partner determine which jobs need attention first — and why.
Fictional firm (“Bristol & Co.”), dummy data, no live system connection.
From a balance to a ranked queue

A partner doesn’t just need to know how much WIP exists. They need a short list of which jobs need attention first — and why.
WIP doesn’t fail loudly. It ages quietly.
WIP — work already performed on a client job but not yet billed — is normal. The risk isn’t that it exists; it’s that it ages quietly. The longer it sits, the harder it is to reconstruct, bill, or defend, and the more likely it eventually gets written down instead of collected.
Most practice-management systems already show a WIP balance somewhere. That’s not the same thing as knowing which jobs need a decision this week. A total is something to interpret. A partner needs a short list of what to look at first — and why.
Start from the data every job already carries
I started from the data every job already carries, not from a chart type. Three signals stood out as things a partner would actually recognize: how long it’s been since a job was last billed, whether its WIP balance is unusually large for its stage, and whether a job marked complete is still carrying unbilled work — a pattern a plain balance report hides.
I kept these as explicit, separate rules rather than a single score, so every flag comes with a stated reason. And I built every threshold as an adjustable setting rather than a fixed constant — what counts as “old” or “large” is a firm-specific judgment, not a universal one.
The solution: built to answer a specific question fast
- Headline KPIs — total WIP, WIP aged past 30 and 60 days, WIP at risk, and jobs at risk
- Automatic risk classification — every job scored Low, Medium, or High
- A searchable, filterable, sortable job table, ranked by risk by default
- A job-level detail view — client, staff, WIP, last invoice date, exact reason flagged, recommended action
- Configurable thresholds, adjustable directly in the interface

Separate rules, each with a stated reason
0–30 Low, 31–60 Medium, 61+ High (adjustable defaults, not an accounting standard).
A job marked complete with unbilled WIP is always High, regardless of age.
WIP above a configurable dollar threshold escalates to High even before it’s old.
Every job carries the specific reason it was flagged — not just a severity label.

One page, no backend, instant recalculation
A single, self-contained HTML/CSS/JavaScript build — no framework, no backend, no database. Seventy-two fictional job records are embedded directly in the page. One function classifies every job against the current thresholds; changing any threshold re-runs that function across all 72 jobs and re-renders the KPIs, summary, and table immediately, entirely in the browser.



Tighten a threshold, and the risk view updates immediately.
Risk that’s visible without anyone looking for it
- A short, prioritized list instead of a balance to interpret
- Risk that’s visible without anyone going looking for it
- A reason and a next step attached to every flag, not just a number
- Room to catch a problem while there’s still a real decision to make
- Thresholds a firm can define for itself, instead of accepting a fixed definition of risk
What I’d do next
This prototype runs entirely on a fictional dataset today, with no connection to Xero, XPM, or FYI. The next step would be replacing that dataset with a real firm’s job, billing, and status data from those systems, mapped onto the structure already built here — then testing whether the rules and thresholds actually hold up against how that firm works, before considering anything beyond a single-firm proof.
Logic, data structure, interface and build
I chose to explore this problem based on my experience building practice-management reporting for an accounting firm, where I saw how much operational detail lives inside systems like Xero, XPM, and FYI without ever surfacing as something a partner can act on. For this project, I designed the risk logic from scratch, defined the data structure — including the risk rules as their own configurable layer — designed the interface around the one question a partner actually asks, and built the complete working prototype, from the dataset through the interactive front end.
Key takeaways
- Can take an operational business problem to a working, interactive prototype without a live client relationship first
- Designs around decisions, not visuals
- Builds configurability in from the start, not as an afterthought
- Comfortable being precise about what something is and isn’t — the prototype label is doing real work here, not hedging
See it running.
No login required — runs entirely in your browser.