Reports MFE · epic #2102 · 27 Aug – 6 Sep 2026

Ten days in, and the money still has nowhere to show up

The backend can now compute what every practitioner and every stakeholder is owed, to the rupee, with the arithmetic tested. Four of the five screens that would show them still do not exist. This page is for deciding what happens next, not for admiring what happened.

17PRs merged
8/9Tiers built
1/5New screens built
6Fixes awaiting QA
11Open defects
3Plans in play

Where the ten days actually went

The plan accounted for about half of it. The rest was correctness work nobody scheduled, and it was not optional — but it is the honest answer to “why are we still a way off”.

Aug 27–31
Days 1–5

The port itselfOn plan

Tiers 0–5 and 7. The data layer, the commission pages re-pointed to domains/billing, revenue sharing, premium reports, exports and the audit trail, tiered commissions, and the polymorphic earner model. Eight PRs. This is what the plan predicted and it ran roughly to shape — because it was re-pointing existing screens, not building new ones.

Aug 31–Sep 5
Days 5–9

Money bugs — and most of them were oursRework

Five separate cases where the payout figure was wrong: commissions deducted from the wrong month, periods bucketed in UTC, settlements never opening the payout gate, tiered commissions never deducted at all, and one tiered run starving another of every item. Every one was money in the facility's favour and none was visible on screen.

Blaming the lines rather than recalling them: eight of the sixteen defects found in this period were introduced by days 1–5 of this epic — three by Tier 8 alone, two by Tier 5, one by Tier 7. This phase was mostly rework on code written the same week, not archaeology on inherited debt. The other eight were genuinely pre-existing, dating from January to May.

Sep 5–6
Days 9–10

A permission refactor that belongs to a different appScope drift

Scoping My Earnings, I went looking for an endpoint that serves an invoice line description, found it ungated, and followed that thread into a platform-wide permission split (#2273 → #2274 → #2275 → #2277) touching 26 policies, a data migration and the CMS queue. The Reports app never needed any of it — CommissionCalculation belongs_to :invoice_item, so the column was always one line on a serializer this app already owns. The bugs are real and worth having. The day spent building them was not this epic's to spend.

Introduced by this epicTierInherited, found hereDates from
#2184 tiered double-payment guard one-directional5#2236 settling never opened the payout gateJan
#2261 REVENUE_GENERATED starves SERVICES5#2238 four different period bucketingsJan
#2271 starved months invisible to the drift report5#2245 can_cancel? casingJan
#2235 tiered commissions never deducted from the pool8#2246 settlement spans facilities, stamped with oneJan
#2237 periods bucketed in UTC8#2272 period filter raises on String boundsJan
#2239 payouts bore the previous month's commission8#2273 invoice read gate is bare membershipJan
#2244 an approved calculation can never be re-run8#2274 one permission pair over two domainsApr
#2275 practitioners lost the ability to bill7#2276 facility summary ungatedMay
The pattern worth naming

Roughly a day of correction per two days of build, and it was review that caught almost all of it — not tests, not QA, not use. Tier 8 produced three money-wrong defects within days of merging; Tier 5 produced two.

That is the most useful number in this document for sizing what is ahead. It also means the remaining defect count is unknown in a specific way: it is bounded by how much reviewing gets done rather than by how much code is left, so it will keep rising while the payout surfaces get attention and stop rising when they do not — which is not the same as being clean.

What exists today

Split by the distinction that actually matters — whether it is machinery or something a person can open.

Backend / machinery

Essentially done

Commission calculation for practitioners and staff, tiered commissions, the facility P&L, stakeholder payouts, the earner scope, the audit trail, exports. Tier 6 (saved reports) is the one unbuilt tier and nothing depends on it.

Screens people open

1 of 5

Facility cost entry is built. My Earnings, My Statement, the revenue waterfall and the four Tier 3 reports are not. Every screen that does exist is an administrator surface — which is precisely the problem the scope plan says the legacy app had.

TierWhat it isState
0Billing-reporting data layerDone
1Commissions pages re-pointedPlus My Earnings — scoped, not builtDone + 1 screen
2Revenue sharing + nested stakeholdersPlus My Statement — not scopedIn QA + 1 screen
3Premium reportsPlus the waterfall and four grounded reports — not builtIn QA + 5 screens
4Exports and audit trailIn QA
5Tiered commissions (backend)Done
6Saved reports and templates (backend)Not started
7Commission earners beyond practitionersDone 1 regression
8Stakeholder payout model + facility cost entryDone 4 fixes in QA

The three plans, and what each is for

Plus one todo list. Everything else in docs/plans/ that mentions commissions belongs to a different lineage.

DocumentSizeRole & current accuracy
2026-08-16-feat-reports-app-port-scope-plan 1,689 The master. Nine tiers, ten decisions, the screen-coverage audit that produced the “five new screens” count. Corrected today: it declared the manage_billing contradiction resolved and listed patient billing as leak surface. That framing is what let Tier 7 close both domains with one change.
2026-08-27-1918-feat-polymorphic-commission-earner-plan 646 Tier 7's implementation plan. Shipped as #2180. Accurate, but it is the source of the #2275 regression — worth reading before touching permissions again.
2026-09-05-feat-my-earnings-scope 442 Tier 1's remaining screen. Merged as #2269, all three decisions settled. Corrected today: it claimed the “earned on” column needed an invoice endpoint and was blocked on the permission work. It needs neither.
todos/2026-09-06-billing-permission-split-followups 76 Five deferrals from #2277, each with why. Belongs with the CMS work, not here — see decision 1.
Nothing is scoped for three of the four missing screens

My Earnings has a 442-line plan with its decisions settled. My Statement, the revenue waterfall and the four Tier 3 reports have a paragraph each in the master plan and nothing more. Any estimate of “how much is left” that treats them as understood is guessing — and the My Earnings plan took a full review round and three decisions from you to become buildable, which is the only real data point available for what scoping one of these costs.

Five decisions

Each with what I would do and what it costs. The first two change what gets worked on tomorrow; the rest shape the finish line.

  1. Does the permission split (#2277) ship with this epic?

    It is complete, twice-reviewed, and closes a live regression we caused in Tier 7. But it changes CMS write paths, carries a data migration over every tenant's permissions, and its QA is “can the front desk raise a bill and take a payment” — nothing to do with Reports.

    Recommendation

    Hand it to whoever owns CMS billing as its own change. Keep the PR, keep the issues, drop it from this epic's sign-off. The one thing that must not wait: #2275 is a live production regression — practitioners cannot raise a bill today, and in a single-doctor practice that means nobody at the clinic can.

    cost of parking: #2275 stays live until CMS picks it up  ·  cost of shipping: Reports QA signs off a CMS billing change
  2. What happens to the months that are already wrong (#2271)?

    #2270 stopped new months going wrong. It repaired none of the ones already wrong, and the drift report is structurally blind to them — a starved run persisted nothing, so both sides of its comparison are wrong in the same direction and the month reads as clean. Practitioners were underpaid; stakeholders overpaid.

    Recommendation

    Start with a query, not a fix. Nobody can size the repair — or judge whether it is worth making — without knowing which facility-months were starved. That is a half-day of investigation that turns an open-ended liability into a number.

    this is the only place money is still wrong, and it is wrong in closed months
  3. Which screens are in v1?

    Four are missing. My Earnings is scoped and buildable now. My Statement is its stakeholder twin — same shape, different data, and the master plan says explicitly to build them against one scope rather than two. The waterfall and the four Tier 3 reports are reporting surfaces over a calculation that already works.

    Recommendation

    My Earnings, then My Statement. Those two are the entire point of Decision 10 — they are what make earners and stakeholders users of this app rather than subjects of it. Ship the waterfall and the Tier 3 reports after, as a second release; they make the calculation legible to administrators who already have screens.

    v1 = 2 screens + their backend gaps  ·  v2 = waterfall + 4 reports
  4. Is Tier 6 in scope at all?

    Saved reports and report templates. No models, no routes, no screens, and nothing else in the epic depends on it. It has been last on every ordering since the plan was written.

    Recommendation

    Cut it from this epic and close #2116 as out of scope, or convert it to a standalone backlog item. Carrying an unbuilt tier makes the programme look 89% done when the thing that actually matters is 20% done.

    no dependency anywhere; pure signal cleanup
  5. Which of the eleven open defects block the release?

    Six fixes are already in QA. Of the eleven still open: one is money already wrong (#2271), two are operator dead ends where the UI offers an action that can never succeed (#2244, #2245), one is a reconciliation mismatch across screens (#2238), one mislabels a settlement (#2246), and five are the CMS permission cluster.

    Recommendation

    Block on #2272 only — it breaks the period selector every new screen needs, so nothing ships without it. Treat #2244 and #2245 as launch-blocking for QA rather than for code: a tester will hit both within an hour and cannot get out. Everything else follows the release.

    #2272 is the single true blocker; the rest is triage

What I would and would not bet on

Confident

The arithmetic. Commission and payout calculation has been through five rounds of correctness work, and every fix landed with tests verified to fail against the unfixed code. The remaining risk there is not “is the number derived correctly” — it is whether the agreements behind it say what people think, and no test can answer that.

My Earnings is buildable now. Decisions settled, backend gaps enumerated, and after today's correction it depends on nothing outside this app.

Not confident

Any estimate for the three unscoped screens. The one screen that went through scoping needed a full review round and three decisions to become buildable, and the review found a security contradiction in the first draft. Assume the same for each of the others rather than treating them as small.

The defect count, and our own defect rate. Half the defects found in the correctness phase came from the five days of building that preceded it. There is no reason to expect the remaining screens to behave differently, so an estimate that counts only build time is wrong by roughly half.

QA throughput. Six fixes are queued behind a QA cycle that has not started, and two of the open dead ends will stall a tester on contact.

If you only take one thing

The backend is not the constraint and has not been for about four days. Every remaining decision is really the same decision — how much of the administrator tooling do we keep polishing before we build the two screens that let people see their own money?