fix(trips): stop reporting a settlement breakdown that cannot be computed
ci / lint-test (push) Successful in 35s
ci / lint-test (push) Successful in 35s
The trip view showed Total Owed / Settled / Unsettled per participant, with the last two derived from transaction_splits.settled. Nothing sets that flag - its only writer was /api/splits/settle, which no UI calls - so it is false on all 673 splits and every trip reported 100% unsettled, including trips already paid in full. Molina has paid $20,782.79 against $19,556.07 of splits and the Europe trip still showed her entire share outstanding. A correct per-trip figure is not computable either: split_payments records only from, to, amount and date, so a payment cannot be attributed to a trip. The trip view now shows each participant's share and points at Shared for what is actually owed, which is where settlement genuinely lives. Also removes /api/splits/settle. It was unreachable from the UI but live on its URL, and a single call with participant_id would mark every one of that person's splits settled - writing a flag nothing reads. Settlement will be reintroduced against settlement contexts (docs/shared-expenses-design.md). getParticipantBalances is deliberately untouched: it computes splits minus payments, which is coherent. Excluding settled splits there while still subtracting the payments that settled them would double-count.
This commit is contained in:
+11
-5
@@ -753,7 +753,7 @@ export interface TripAnalytics {
|
||||
daily_spend: { date: string; amount: number }[];
|
||||
top_merchants: { merchant: string; amount: number; count: number }[];
|
||||
tag_breakdown: { tag_id: number; name: string; color: string; amount: number; count: number }[];
|
||||
participant_splits: { participant_id: number; name: string; owed: number; settled: number; unsettled: number }[];
|
||||
participant_splits: { participant_id: number; name: string; owed: number }[];
|
||||
}
|
||||
|
||||
export async function getTrips(ownerId: number): Promise<TripRow[]> {
|
||||
@@ -857,13 +857,19 @@ export async function getTripAnalytics(tripId: number, ownerId: number): Promise
|
||||
ORDER BY 4 DESC
|
||||
`, [tripId]),
|
||||
|
||||
queryRaw<{ participant_id: number; name: string; owed: number; settled: number; unsettled: number }>(`
|
||||
// No settled/unsettled breakdown here. It was computed from
|
||||
// transaction_splits.settled, which only /api/splits/settle writes and
|
||||
// nothing in the UI calls — so it is false on all 673 splits and every trip
|
||||
// reported 100% unsettled, including trips paid in full. A real per-trip
|
||||
// figure is not computable either: split_payments carries no trip
|
||||
// attribution, so a payment cannot be assigned to a trip. Settlement is a
|
||||
// property of the whole relationship until settlement contexts exist
|
||||
// (see docs/shared-expenses-design.md).
|
||||
queryRaw<{ participant_id: number; name: string; owed: number }>(`
|
||||
SELECT
|
||||
p.id AS participant_id,
|
||||
p.name,
|
||||
SUM(ts.share_percent / 100.0 * COALESCE(tx.amount_aud, tx.amount))::float AS owed,
|
||||
SUM(CASE WHEN ts.settled THEN ts.share_percent / 100.0 * COALESCE(tx.amount_aud, tx.amount) ELSE 0 END)::float AS settled,
|
||||
SUM(CASE WHEN NOT ts.settled THEN ts.share_percent / 100.0 * COALESCE(tx.amount_aud, tx.amount) ELSE 0 END)::float AS unsettled
|
||||
SUM(ts.share_percent / 100.0 * COALESCE(tx.amount_aud, tx.amount))::float AS owed
|
||||
FROM transaction_overrides o
|
||||
JOIN transactions tx ON tx.id = o.transaction_id
|
||||
JOIN transaction_splits ts ON ts.transaction_id = tx.id
|
||||
|
||||
Reference in New Issue
Block a user