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