Skip to content

Work / Aakalan / Wiki / Concepts

payment-methods

Conceptverified 2026-10-30

payment-methods

A person is not one number and one UPI ID. PersonView carries phones: string[] and payments: PaymentMethod[], because one person routinely has a personal number and a work one, and a personal VPA, a work VPA and a bank account. Which to use is the payee's call, so all are kept and all are offered, never guessed at.

hasAccount(person) says whether they are a real Aakalan user. Someone added by name or from contacts gets a local:-prefixed id: the ledger is correct for its owner and nothing reaches them until they install the app. There the UI must offer an invite, not present them as reachable.

UPI is the only kind that can be added. Aakalan cannot start a bank transfer, so a full account number and IFSC would be credentials collected for no purpose, and last-four-only left a row nobody could pay. It read as an unfinished form.

The 'bank' kind stays in PaymentMethodKind and existing rows keep working, shown read-only with a line explaining why, plus a Remove button. Narrowing the union would make every stored bank row an unrepresentable state that migratePerson must coerce, and would silently delete a user's own record, including notes about other people in people[].payments. Deleting someone's data to tidy a type is not a refactor.

Settlement.method keeps 'bank' regardless: recording THAT a transfer happened differs from offering somewhere to send one, and the settle screen still needs it.

Aakalan never handles UPI PINs, card or bank credentials. Payments hand off to the user's UPI app by intent and wait for the callback. Do not build a card form.

Related: upi-cannot-pay-a-number, settle-no-upi