diff --git a/src/app/shared/page.tsx b/src/app/shared/page.tsx index d1039f3..0a64b98 100644 --- a/src/app/shared/page.tsx +++ b/src/app/shared/page.tsx @@ -299,6 +299,9 @@ export default function SharedPage() { {addingParticipant && setAddingParticipant(false)} />} {/* Balance cards */} + {realTagIds.length === 0 && tagIds.includes("untagged") ? null : realTagIds.length > 0 && ( +

Showing split totals for selected tag — payments excluded (payments settle overall debt, not per-tag)

+ )}
{balLoading ? (

Loading balances...

diff --git a/src/lib/queries.ts b/src/lib/queries.ts index a11b301..8e5894d 100644 --- a/src/lib/queries.ts +++ b/src/lib/queries.ts @@ -287,10 +287,25 @@ export async function getParticipantBalances(ownerId: number, tagIds?: number[]) tagFilter = `AND EXISTS (SELECT 1 FROM transaction_tags tt WHERE tt.transaction_id = t.id AND tt.tag_id = ANY($2::int[]))`; } + // Payments settle the total relationship between two people, not a specific tag. + // Only subtract payments when viewing the unfiltered total; with a tag filter + // active, show the raw split amount for that tag context only. + const paymentsJoin = tagIds?.length ? "" : ` + LEFT JOIN ( + SELECT + CASE WHEN sp.from_participant_id != $1 THEN sp.from_participant_id ELSE sp.to_participant_id END AS pid, + SUM(CASE WHEN sp.to_participant_id = $1 THEN sp.amount ELSE -sp.amount END) AS net_paid + FROM split_payments sp + WHERE sp.from_participant_id = $1 OR sp.to_participant_id = $1 + GROUP BY pid + ) payments ON payments.pid = p.id`; + const paymentsSelect = tagIds?.length ? "" : "- COALESCE(payments.net_paid, 0)::numeric(12,2)"; + const paymentsGroup = tagIds?.length ? "" : ", payments.net_paid"; + return queryRaw(` SELECT p.id, p.name, COALESCE(SUM(splits.signed_amount), 0)::numeric(12,2) - - COALESCE(payments.net_paid, 0)::numeric(12,2) AS total_owed, + ${paymentsSelect} AS total_owed, COALESCE(SUM(splits.split_count), 0)::int AS unsettled_count FROM participants p @@ -317,19 +332,10 @@ export async function getParticipantBalances(ownerId: number, tagIds?: number[]) WHERE ts.participant_id = $1 AND COALESCE(t.owner_id, s.owner_id) != $1 ${tagFilter} ) splits ON splits.pid = p.id - - -- Net payments always unfiltered (payments are against total debt, not per-tag) - LEFT JOIN ( - SELECT - CASE WHEN sp.from_participant_id != $1 THEN sp.from_participant_id ELSE sp.to_participant_id END AS pid, - SUM(CASE WHEN sp.to_participant_id = $1 THEN sp.amount ELSE -sp.amount END) AS net_paid - FROM split_payments sp - WHERE sp.from_participant_id = $1 OR sp.to_participant_id = $1 - GROUP BY pid - ) payments ON payments.pid = p.id + ${paymentsJoin} WHERE p.id != $1 - GROUP BY p.id, p.name, payments.net_paid + GROUP BY p.id, p.name ${paymentsGroup} ORDER BY p.name `, params); }