diff --git a/static/gsAdmin/views/invoiceComparison.tsx b/static/gsAdmin/views/invoiceComparison.tsx
index 773bb528996dba..eb724538c4f11c 100644
--- a/static/gsAdmin/views/invoiceComparison.tsx
+++ b/static/gsAdmin/views/invoiceComparison.tsx
@@ -27,9 +27,9 @@ type RowStatus = 'match' | 'mismatch' | 'legacy_only' | 'platform_only';
type Row = {
delta_cents: number;
delta_pct: number | null;
- legacy_amount: number | null;
// guid is present only when the side has exactly one invoice in the window
// (otherwise there's no single invoice to deep-link to).
+ legacy_amount: number | null;
legacy_invoice_count: number;
legacy_invoice_guid: string | null;
organization_id: number;
@@ -43,9 +43,9 @@ type Row = {
type Summary = {
end: string;
legacy_count: number;
- legacy_total_cents: number;
+ over_threshold_count: number;
+ over_threshold_pct: number;
platform_count: number;
- platform_total_cents: number;
queried_at: string;
row_count: number;
rows_page: number;
@@ -93,14 +93,6 @@ function formatDollars(cents: number | null) {
return `$${dollars.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}`;
}
-function formatPercent(pct: number | null) {
- if (pct === null) {
- // No legacy baseline — sorts to top of the list.
- return ∞;
- }
- return `${(pct * 100).toLocaleString(undefined, {minimumFractionDigits: 1, maximumFractionDigits: 1})}%`;
-}
-
// Render a dollar amount, deep-linking to the org-scoped invoice detail page
// when we have both the org slug and a single invoice's guid. The receipts
// page (CustomerInvoiceDetailsEndpoint) resolves legacy and platform invoices
@@ -123,6 +115,43 @@ function InvoiceAmount({
return {amount};
}
+function formatPercent(pct: number | null) {
+ if (pct === null) {
+ // No legacy baseline — sorts to top of the list.
+ return ∞;
+ }
+ return `${(pct * 100).toLocaleString(undefined, {minimumFractionDigits: 1, maximumFractionDigits: 1})}%`;
+}
+
+// `formatPercent` renders ``null`` as ``∞`` because for ``delta_pct`` rows
+// a missing percentage means "undefined drift" (legacy=$0 with non-zero
+// platform — sorts to the top of the list). That semantic doesn't apply
+// to summary ratios like ``over_threshold_pct`` / ``unmatched_invoice_pct``,
+// where a runtime ``null``/``undefined`` would just mean the backend
+// didn't populate the field (deploy-window race, response-shape drift).
+// Render those as ``N/A`` instead of pretending the metric blew up.
+function formatPercentOrNA(pct: number | null | undefined) {
+ if (pct === null || pct === undefined) {
+ return N/A;
+ }
+ return `${(pct * 100).toLocaleString(undefined, {minimumFractionDigits: 1, maximumFractionDigits: 1})}%`;
+}
+
+// Same deploy-window-race rationale as `formatPercentOrNA`: the type
+// declares these as `number` but a stale-cached response or any future
+// shape drift could leave them runtime-`undefined`, which would render
+// the literal string "undefined" in the UI. NaN is also caught — it
+// shows up when arithmetic propagates an undefined operand (e.g.
+// `legacy_count + platform_count` for the Unmatched denominator).
+// Falling back to an em dash matches the missing-value affordance
+// `formatDollars` already uses.
+function formatCountOrNA(n: number | null | undefined) {
+ if (n === null || n === undefined || Number.isNaN(n)) {
+ return —;
+ }
+ return n.toLocaleString();
+}
+
// `datetime-local` inputs use the user's local timezone with no offset
// in the string (e.g. "2026-05-26T22:30"). Format a Date for that field.
function toDatetimeLocalValue(d: Date): string {
@@ -433,11 +462,11 @@ export function InvoiceComparison() {
Summary
@@ -446,7 +475,7 @@ export function InvoiceComparison() {
Legacy invoices
- {data.summary.legacy_count}
+ {formatCountOrNA(data.summary.legacy_count)}
@@ -454,41 +483,19 @@ export function InvoiceComparison() {
Platform invoices
- {data.summary.platform_count}
-
-
-
-
- Legacy total
-
-
- {formatDollars(data.summary.legacy_total_cents)}
+ {formatCountOrNA(data.summary.platform_count)}
- Platform total
+ {'>1% diff'}
- {formatDollars(data.summary.platform_total_cents)}
-
-
-
-
- Total delta
-
-
- {formatDollars(
- data.summary.legacy_total_cents - data.summary.platform_total_cents
- )}
-
-
-
-
- Rows
-
-
- {data.summary.row_count}
+ {formatPercentOrNA(data.summary.over_threshold_pct)}
+
+ ({formatCountOrNA(data.summary.over_threshold_count)} of{' '}
+ {formatCountOrNA(data.summary.row_count)})
+
@@ -496,10 +503,13 @@ export function InvoiceComparison() {
Unmatched
- {formatPercent(data.summary.unmatched_invoice_pct)}
+ {formatPercentOrNA(data.summary.unmatched_invoice_pct)}
- ({data.summary.unmatched_invoice_count} of{' '}
- {data.summary.legacy_count + data.summary.platform_count})
+ ({formatCountOrNA(data.summary.unmatched_invoice_count)} of{' '}
+ {formatCountOrNA(
+ data.summary.legacy_count + data.summary.platform_count
+ )}
+ )