Skip to content

Let an expense's payer invite people - #73

Merged
aquasolterra merged 2 commits into
mainfrom
invited-beneficiaries
Sep 18, 2026
Merged

aquasolterra merged 2 commits into
mainfrom
invited-beneficiaries

Conversation

@aquasolterra

Copy link
Copy Markdown
Member

An expense's payer can now mark people they paid for as invited: those people owe nothing back for it. Say Ann pays 90 for Ann, Bo and Cy, and Bo is her guest. Then only Cy owes Ann 30, and the cost doesn't have to be split in two.

Model and math

  • New column CostBeneficiaries.invited (schema v38, addColumn guarded by from >= 10). The flag is set per beneficiary, not per cost.
  • computeTripStats takes invitedByCost. The guest keeps their share in shareMinor, and totals and categories don't change. The share goes into the guest's invitedMinor and the payer's hostedMinor, and borneMinor = share − invited + hosted feeds netMinor. mergeTripStats pools both fields.
  • An invitation only counts on an expense with a payer, for someone other than the payer, on an explicit split (not the participant fallback). The stats ignore it anywhere else, and CostController and the importer never store it there.

UI

  • Cost form: tapping a "paid for" chip toggles the invitation; invited people show the volunteer_activism icon. A tristate "Invited by {payer}" box invites everyone or clears all invitations.
  • Statistics, balances view: new lines "invited to X" and "invited others to X". The reimbursement line's "own cost" now counts invitations too.

Elsewhere

  • Routines: the flag is copied with a routine's fare.
  • .tpt: exported as v6 only when the trip uses the flag, because an older app would show the guest owing their share. invited is written only when non-empty.
  • PDF: no change. It prints neither splits nor balances.

Tests

  • Stats unit tests, DAO tests, routine copy, bundle round trip plus v6 stamping, import sanitizing, the v37→v38 migration, and form and stats-screen widget tests.
  • 13 older migration tests now create cost_beneficiaries in their hand-written schemas; every real database from v10 onward has that table. The v37 test also drops the new column.

CHANGELOG, docs/features.md and AGENTS.md are updated.

🤖 Generated with Claude Code

aquasolterra and others added 2 commits September 18, 2026 23:25
A beneficiary can now be marked invited (`CostBeneficiaries.invited`,
schema v38): the payer paid for them and does not want it back. Per
beneficiary, so one dinner can hold a guest and somebody who repays.

The share stays the guest's and totals and categories do not move;
`computeTripStats` books it to the guest's `invitedMinor` and the payer's
`hostedMinor`, which the balance reads. It only counts on an expense with
a payer, for someone other than the payer, on an explicit split.

The form toggles it on the "paid for" chips, plus a tristate
"Invited by {payer}" box. It travels with a routine's fare, and a trip
using it is exported as `.tpt` v6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 18, 2026

Copy link
Copy Markdown

@aquasolterra
aquasolterra merged commit 487fa27 into main Sep 18, 2026
5 checks passed
@aquasolterra
aquasolterra deleted the invited-beneficiaries branch September 18, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant