diff --git a/docs/2026-08-15-thirty-day-reconciliation.html b/docs/2026-08-15-thirty-day-reconciliation.html index d4888054..3e6b8cb6 100644 --- a/docs/2026-08-15-thirty-day-reconciliation.html +++ b/docs/2026-08-15-thirty-day-reconciliation.html @@ -279,7 +279,22 @@
-

The second pattern is worth reading carefully: Card Payments falls by exactly what Fees gains, so the day stays balanced while the split between the two lines changes. That is a data-freshness effect from re-importing, not a change in how anything is calculated.

+

The second pattern is worth reading carefully: Card Payments falls by exactly what Fees gains, so the day stays balanced while the split between the two lines changes. That is a data-freshness effect from re-importing, not a change in how anything is calculated. Three real rows:

+
+
+ + + + + + + + + +
ClientDateLineBeforeAfter
NGAN2026-08-12Card Payments1,237.231,207.64
Fees0.0029.59
NGVC2026-08-10Card Payments2,025.032,074.63
Fees49.600.00
NGGP2026-08-13every line0.00real figures
+
+
+

NGAN moves $29.59 out of Card Payments and into Fees; NGVC moves $49.60 the other way. Both stay balanced to the cent. NGGP is the first pattern — production held an all-zero summary for a day with $2,478.44 of card payments, $1,148.11 of gyros and pitas, and so on.

@@ -351,6 +366,69 @@ +
+

Worked examples

+
+

Each fix is easiest to check on a single order. In every case below the day's imbalance equals the fix amount exactly, which is what you would expect if the fix is booking something real that was previously booked nowhere.

+
+ +

R1 — a tip reversal with no tender to hang it on

+
+ + + + + + + + + +
FieldValue
Ordersquare/order/NGLK-SM-OxSX9gpXJV394qqT8mnBGypUwKNZY
:sales-order/tip−60.00
:sales-order/total−60.00
:sales-order/charges0 — no tender at all
NGLK 2026-08-04 imbalance−60.00 → 0.00
+
+
+

A guest's tip was handed back. The reversal is recorded on the order, but get-tip reaches tips by joining through :sales-order/charges, and a return-only order has no charge to join through — so the −$60.00 was invisible and the day credited a tip that no longer existed. The other four largest R1 repairs are the same shape: NGFF 08-01 (−$40.00), NGSG 07-29 (−$40.00), NGNV 08-09 (−$35.00), NGJS 07-25 (−$35.00).

+
+ +

R2 — a service charge collected but credited nowhere

+
+ + + + + + + + +
FieldValue
Ordersquare/order/NTPT-PT-KrMZzcon1cpQEJUyetErkBIpcdEZY
:sales-order/service-charge427.10
:sales-order/total3,198.78
NTPT 2026-08-06 imbalance+427.10 → 0.00
+
+
+

The $427.10 is inside the card tender the customer paid, so it lands on the debit side — but nothing credited it, leaving the day short by exactly that amount. Next largest: NGFO 07-16 ($275.23), NGRN 08-06 ($236.96), N-30008 07-24 ($229.42), N-30003 07-18 ($225.00).

+
+ +

The 19 days the data work unbalanced — and all 19 rescued

+
+ + + + + + + + + + + + + + + +
ClientDateAfter data fixAfter R1 + R2
NGSF2026-08-13+137.990.00
NGRY2026-08-13+103.260.00
NGDS2026-08-13+100.520.00
NGDV2026-08-13+100.520.00
N-300072026-08-13+86.000.00
N-300032026-08-13+83.530.00
NGSC2026-08-13+75.000.00
NGGH2026-08-13+75.000.00
NGDG2026-08-13+70.000.00
NGDU2026-08-13+70.000.00
All 19 daysunbalancedbalanced
+
+
+

These are days production held an empty summary for — trivially balanced at zero. Filling them in with real figures exposes the same two calculation gaps every other day had, and both fixes then close them. Not one of the 19 survives as a regression. Their clustering on 08-13 is expected: it is the most recent day, so it is the one production had least chance to compute.

+
+
+

Days production never had

@@ -382,7 +460,7 @@ - + @@ -392,6 +470,7 @@

The ten-cent threshold separates register rounding from real variance with nothing sitting near the boundary — the largest sub-threshold day is 9.00¢ and the smallest material one is $9.62, two orders of magnitude apart.

+

NGBK 2026-08-06, traced. Summing that client-day's orders directly: tender totals $6,358.99 while the orders' own totals come to $6,059.57 — a difference of $299.42, exactly the imbalance. Square recorded more payment than the orders account for. Three explanations were checked and ruled out: the day has no refund lines at all, no order carries two charges for one payment id, and the nine orders lacking line items carry zero tender. This is a source-data discrepancy, not a calculation defect, and not something either fix should paper over.

@@ -412,6 +491,50 @@ +
+

Reproduce it

+
+

Every figure here comes from the restored database and can be re-derived from it. The comparison tool is committed as auto-ap.jobs.compare-sales-summaries.

+
+
+
;; connect to the restored backup (read-only is fine)
+(def conn (d/connect "datomic:dev://localhost:4337/integreat-prod-restore"))
+
+;; the whole comparison: production's own summaries vs now
+(require '[auto-ap.jobs.compare-sales-summaries :as cs])
+(def r (cs/compare-against 209608347
+                          (clj-time.core/date-time 2026 7 15)
+                          (clj-time.core/date-time 2026 8 14)))
+
+(:tally r)                                  ;; identical / numbers-changed / added
+(:balance-transitions r)                    ;; the four-way counts
+(count (:previously-balanced-and-changed r)) ;; => 237
+
+;; what actually moved on one of those days
+(cs/line-diff (first (:previously-balanced-and-changed r)))
+
+;; the single order behind the R1 example
+(d/pull (d/db conn) '[*]
+        [:sales-order/external-id
+         "square/order/NGLK-SM-OxSX9gpXJV394qqT8mnBGypUwKNZY"])
+
+;; the single order behind the R2 example
+(d/pull (d/db conn) '[*]
+        [:sales-order/external-id
+         "square/order/NTPT-PT-KrMZzcon1cpQEJUyetErkBIpcdEZY"])
+
+
+

The unit tests covering both fixes and the re-key run with:

+
+
+
lein test auto-ap.jobs.sales-summaries-test auto-ap.square.core3-test
+;; => 15 tests, 26 assertions, 0 failures
+
+
+

Note that the restore currently has Phase 0 applied and the twins deactivated. Re-running the comparison after re-activating them will move the contended clients' figures; everything outside those ten client pairs is unaffected.

+
+
+
Measured 2026-08-15 on integreat-prod-restore. Branch worktree-sales-summary-balance. Service charges map to account 49000 Service Income, chosen to make measurement possible and still pending accounting sign-off. The account affects only whether a day can reach accepted — never whether it balances — so no figure here depends on it.
ClientDateVarianceExplanation
NGBK2026-08-06+$299.42refunds now held by both twins — a re-key consequence
NGBK2026-08-06+$299.42tender exceeds order totals by exactly this much, in the source data
NGDA2026-08-01−$50.00auto-gratuity booked as a service charge
NGEB2026-08-10−$25.00ezCater fee semantics predicted
NGEB2026-07-29−$20.00ezCater fee semantics predicted