docs(sales-summaries): state how much of the re-key is actually finished

The report implied the shared-payment problem was solved. Measuring the whole
database shows it is solved for refunds, payouts and shifts, and 1.6% solved for
card payments:

  refunds             51,986 scoped · 0 unscoped
  payouts            144,652 scoped · 0 unscoped · 36 with no owner
  cash-drawer shifts  69,291 scoped · 0 unscoped
  card payments      259,763 scoped · 14,241,890 unscoped · 2,122,161 no owner

Sampling 2% of the orders belonging to every client that has ever contended
found 12,954 payments still owned by two orders, extrapolating to roughly
650,000 across that population.

So the balance figures are what the calculation fixes are worth on data where
the sharing had been resolved for the clients and period measured — not a claim
that the database is clean. The report now says so, and the headline stat that
claimed zero shared payments has been replaced with the 1.6% actually renamed.

Records what finishing requires: renaming is driven from orders, so it means
walking all 19,040,296 of them rather than the clients that look shared today,
since nine pairs contended in the past without sharing a location now. Measured
at ~15,000 orders/hour once the 29 GB database stopped fitting in memory — the
same code did 267,012 in 100 seconds with a warm cache — so it belongs in a
maintenance window on sized hardware. It is resumable and a second pass is a
no-op.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 15:46:30 -07:00
parent c3d95cba6a
commit 74a070e545

View File

@@ -120,7 +120,7 @@
<div class="stat"><span class="k num">1,172</span><span class="l">client-days brought into balance</span></div>
<div class="stat zero"><span class="k num">0</span><span class="l">days knocked out of balance</span></div>
<div class="stat"><span class="k num">97.3%</span><span class="l">of the variance removed</span></div>
<div class="stat zero"><span class="k num">0</span><span class="l">shared payment records left</span></div>
<div class="stat"><span class="k num">1.6%</span><span class="l">of card payments renamed so far</span></div>
</div>
<div class="measure">
@@ -457,6 +457,66 @@
</div>
</section>
<section>
<h2>How complete is this, really</h2>
<div class="measure">
<p>The importer deliberately understands both the old and new record names, so the change can
be deployed before the renaming finishes. That tolerance is a bridge, not a destination —
while any record still carries an unscoped name, two clients can still land on it, and the
guarantee rests on a convention rather than on the data.</p>
<p>Measuring the whole database rather than the part that was migrated gives an honest
picture, and it is not a flattering one.</p>
</div>
<div class="scroll">
<table>
<thead><tr><th>Record type</th><th class="n">Client-scoped</th><th class="n">Still unscoped</th><th class="n">No owner to scope by</th></tr></thead>
<tbody>
<tr><td>Refunds</td><td class="n good">51,986</td><td class="n good">0</td><td class="n good">0</td></tr>
<tr><td>Payouts</td><td class="n good">144,652</td><td class="n good">0</td><td class="n">36</td></tr>
<tr><td>Cash-drawer shifts</td><td class="n good">69,291</td><td class="n good">0</td><td class="n good">0</td></tr>
<tr><td><strong>Card payments</strong></td><td class="n">259,763 <span class="dim">(1.6%)</span></td><td class="n bad">14,241,890</td><td class="n">2,122,161</td></tr>
</tbody>
</table>
</div>
<div class="measure">
<p>Refunds, payouts and shifts are done. <strong>Card payments are not</strong> — the migration
described above covered the ten clients sharing a location today, within the reporting window,
which is 1.6% of them. And sampling 2% of the orders belonging to every client that has
<em>ever</em> contended found <strong>12,954 payments still owned by two orders</strong>, which
extrapolates to roughly 650,000 across that population.</p>
<p>So the correct reading of the balance figures earlier in this report is: they are what the
calculation fixes are worth, measured on data where the sharing had been resolved for the
clients and period in question. They are not a claim that the whole database is clean.</p>
</div>
<div class="callout warn">
<span class="h">What finishing it requires</span>
<p>Renaming has to be driven from orders, because a payment's rightful owner is whichever order
refers to it — so completing it means walking all 19,040,296 orders, not just the clients that
look shared today. Nine client pairs contended in the past without sharing a location now, and
a migration scoped to the current configuration misses every one of them.</p>
<p>On the test machine this ran at roughly 15,000 orders an hour once the database no longer
fitted in memory, which puts a full pass in days rather than hours. That is a hardware
characteristic of a swapping 29 GB restore, not a property of the work: the same code
completed 267,012 orders in 100 seconds when the cache was warm. It belongs in a maintenance
window on properly sized hardware, and it is resumable and safe to re-run — a second pass over
already-renamed records does nothing at all.</p>
</div>
<div class="measure">
<p><strong>The finish line is measurable, not a judgement call.</strong>
<code>unscoped-report</code> counts, for every record type, how many names are client-scoped,
how many are still unscoped, and how many have no owner. Two things follow from it:</p>
<ul>
<li>While the unscoped count is above zero, keep the importer's understanding of both name
forms. Removing it early would strand every record that had not yet been renamed.</li>
<li>Once it reaches zero and stays there across a full import cycle, delete the fallback.
At that point two clients sharing a location is structurally incapable of producing a shared
record, rather than merely unlikely to.</li>
</ul>
</div>
</section>
<section>
<h2>Decisions and risks still open</h2>
<div class="scroll">