Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05 — Screen Inventory (Payments)

Every screen in the payments module. States, permissions, a11y, analytics per screen.

Screen codes: S1 Payments list · S2 Payment detail · S3 New payment · S4 Refund sheet · S5 Reconcile sheet · S6 Receipt view · S7 Receipts list · S8 Payment on invoice (context).


S1 — Payments list

  • Purpose: browse all tenant payments, newest first; drill into details; record new.
  • Route: /payments
  • Entry: Fees tab → Payments; deep link; after successful payment.
  • Exit: payment detail, new payment, receipts list.
  • Widgets: AppSearchBar (client-side filter), status FilterChips (client-side), AppCard/AppListTile rows (transactionReference, amount, payerName, gateway icon, status AppBadge, date), FAB "Record payment", pagination footer.
  • Buttons: FAB (primary CTA), row menu (overflow).
  • States: loading skeleton (8 rows) → empty → error (retry) → data; offline banner.
  • Pagination: page/limit (default 20) via server {data,total}; "Load more" button (no auto-scroll).
  • Permissions: visible with payments.read (client-gated; server (planned)).
  • Keyboard: Enter submits filter; / focuses search (desktop).
  • Responsive: single column phone; two-column grid tablet; table + filters desktop.
  • A11y: rows announce "Payment TXN-… amount … status"; status never color-only (icon + label).
  • Micro-interactions: row tap ripple; status chip pop on update.
  • Analytics: payments.list.view, payments.list.filter, payments.list.open_detail.

S2 — Payment detail

  • Purpose: full payment record + linked invoice + receipt access + actions.
  • Route: /payments/:id
  • Entry: list tap, deep link, notification.
  • Exit: receipt, refund/reconcile sheets, invoice detail.
  • Sections: payment header (amount large, status badge, transaction reference), payer info card, invoice link card (status, paidAmount), gateway + timestamps card, refund history (refundedAmount vs amount), actions.
  • Actions: Receipt (primary tonal), Refund (destructive, only COMPLETED), Reconcile (only PENDING/PROCESSING), Copy transaction reference.
  • States: skeleton → data / 404 error (RESOURCE_NOT_FOUND empty state with copy "Payment not found").
  • Permissions: view payments.read; actions gated payments.refund / payments.reconcile (hide when absent).
  • A11y: money amounts tabularFigures; actions ≥ 48 dp.
  • Analytics: payments.detail.view, payments.detail.refund_start, payments.detail.reconcile.

S3 — New payment (form screen)

  • Purpose: record a payment; always server-confirmed (never optimistic).
  • Route: /payments/new (or prefilled via invoice context)
  • Widgets: amount field (decimal, prefilled from invoice), currency (default USD, read-only until server supports multi-currency), gateway dropdown (enum incl. cash/cheque/bank_transfer), gatewayTransactionId (optional, gateway methods), invoice picker (optional, searchable), payer fields (name, email, id — optional), description, submit "Record payment" with loading spinner.
  • States: pristine → validation errors → submitting (button spinner, fields locked) → success (payment + receipt card) → failure (error banner + retry).
  • Keyboard: amount numeric-decimal; payer email email type.
  • Permission: payments.process.
  • Analytics: payments.new.submit, payments.new.success, payments.new.failed.

S4 — Refund sheet (bottom sheet)

  • Purpose: full/partial refund with reason.
  • Route: modal from S2.
  • Widgets: refundable amount display, amount field (default = full), reason (required), submit, destructive styling.
  • Errors: 409 messages inline/banner; refund amount > payable blocked client-side (min 0, max = amount − refundedAmount).
  • Analytics: payments.refund.submit, payments.refund.success, payments.refund.failed.

S5 — Reconcile sheet

  • Purpose: set payment status from gateway outcome.
  • Widgets: status selector (success → completed / failed → failed / other → pending), optional gateway response text, submit.
  • Permission: payments.reconcile.
  • Analytics: payments.reconcile.submit.

S6 — Receipt view

  • Purpose: display receipt (data row) for printing/sharing.
  • Route: /payments/receipts/:receiptId
  • Sections: header (receipt number, issuedAt), payment reference, amount/fee/currency, payer, description, invoice ref.
  • Actions: Share/Print (planned) via reports; Copy receipt number.
  • State: 404 empty state if missing.
  • Analytics: payments.receipt.view, payments.receipt.share.

S7 — Receipts list

  • Purpose: browse all receipts (paged, newest first).
  • Route: /payments/receipts
  • Mirrors S1 with receipt rows; tap → S6.
  • Analytics: payments.receipts.view.

S8 — Payment context on invoice detail (fees module)

  • Invoice detail shows payments tab/row list (GET /payments/invoice/:invoiceId), paidAmount progress, "Record payment" entry point. Details owned by fees docs.