fix(trips): carry the currency and reconcile rules into the trip figure
ci / lint-test (pull_request) Failing after 43s
ci / lint-test (push) Failing after 43s

a4ab543 landed six hours ago and this branch rewrote one of the queries it
had just fixed, quietly dropping both of its guarantees.

That commit made EXCLUDE_RECONCILED_SOURCE "one fragment both sides import"
because an inlined copy is how the reconciled-row exclusion drifted out of
the analytics routes and double-counted 48 rows / $4,474.79. The trip owed
query here had hand-inlined its own copy — the fragment assumes the alias
`t` and this query used `tx`, so the path of least resistance was to
re-create exactly the divergence that was being removed. Aliased to `t` so
the fragments apply directly.

The same commit made balances count rows whose AUD value is unknown rather
than netting a foreign figure against AUD ones. The trip figure had no
equivalent — on the query where it matters most, because a trip is where
foreign rows actually live. A Europe total silently mixing EUR into AUD is
the whole failure that fix was written to prevent.

The column header still read "Share of this trip" while the number is now
net of payments, which is the same class of drift a4ab543 set out to fix.
It reads "Outstanding on this trip", carries the approx/unconverted caveat
the Shared cards use, and greys a settled zero.
This commit is contained in:
2026-07-27 23:15:28 +10:00
parent 689fadc8b9
commit ae23b03d5d
2 changed files with 42 additions and 14 deletions
+11 -2
View File
@@ -277,7 +277,7 @@ export default function TripDetailPage({ params }: { params: Promise<{ id: strin
<table className="w-full text-sm">
<thead>
<tr className="border-b border-zinc-800">
{["Person", "Share of this trip"].map((h) => (
{["Person", "Outstanding on this trip"].map((h) => (
<th
key={h}
className={`px-5 py-2.5 text-xs text-zinc-500 font-medium ${h === "Person" ? "text-left" : "text-right"}`}
@@ -291,7 +291,16 @@ export default function TripDetailPage({ params }: { params: Promise<{ id: strin
{participant_splits.map((p) => (
<tr key={p.participant_id} className="border-b border-zinc-800/50 last:border-0">
<td className="px-5 py-3 font-medium">{p.name}</td>
<td className="px-5 py-3 text-right tabular-nums font-mono">${Number(p.owed).toFixed(2)}</td>
<td className="px-5 py-3 text-right tabular-nums font-mono">
<span className={Math.abs(Number(p.owed)) < 0.005 ? "text-zinc-500" : ""}>
${Number(p.owed).toFixed(2)}
</span>
{p.unconverted_count > 0 && (
<span className="block text-[11px] text-amber-500/80 mt-0.5 font-sans">
approx · {p.unconverted_count} unconverted
</span>
)}
</td>
</tr>
))}
</tbody>