Transactions
The ledger view — every income, expense, and transfer.
The Transactions tab is where every ledger entry for a client lives, no matter how it got there. Hand-entered, OCR'd from a receipt, imported from CSV — they all surface in one list.
Open it from any client → Transactions.
The list
Each row shows:
- Date — sortable
- Vendor or payer as the primary label; an amber dot appears next to the name if the AI flagged the entry as non-deductible or partially deductible
- Account badge — the CoA code this row is booked to (e.g.
500-200) - Reviewed ✓ — green check if a teammate signed off (see Month-end close)
- Amount on the right — green for income, neutral for expense, grey for transfer; sortable
The list is sorted newest first by date by default. Click any header to re-sort. Up to 1,000 rows per filter window — if the truncation banner appears, narrow the date range with the filter bar.
Filtering and searching
Above the list, two controls let you narrow the data:
- Search box — free-text across vendor, description, and account (case-insensitive). Results update as you type.
- Multi-filter chips — add one or more structured rules via + Add filter. Each chip shows the active condition; click it to edit or remove it.
Using the multi-filter
Click + Add filter to open the filter editor:
- Column — pick what to filter on: Date, Vendor, Account, or Amount
- Operation — changes based on the column type:
- Text: contains / does not contain / is / is not
- Number: equals / not equals / greater than / less than / between
- Date: equals / not equals / after / before / between
- Value — type a value or pick a date from the calendar. For between, set both start and end.
- Apply — commits the rule and closes the editor.
Applied rules are shown as chips below the search box. Click any chip to reopen its editor and tweak the rule. Hit × on a chip to remove that rule.
Multiple rules work as AND — all active rules must match for a row to appear.
The filter chip state is local to the page — it isn't persisted in the URL. If you need to share a specific filtered view with a teammate, do so via the search box (which is URL-driven) or describe the filter rules verbally.
Adding a transaction manually
Hidden from Viewers; available to everyone else. Click Add transaction above the list. The form asks for:
| Field | Notes |
|---|---|
| Date | Required |
| Type | Required — Income / Expense / Transfer |
| Subtotal | Required, positive, tax-exclusive |
| SST | Optional. Auto-filled if you pick a tax code with a default rate. Hidden for transfers — a bank-to-bank move carries no SST |
| Total | Read-only — subtotal + SST, shown so you can sanity-check |
| Currency | Required. MYR / USD / SGD today |
| Vendor or payer | Free text |
| Account | Searchable dropdown of the client's chart of accounts. Limited to active codes. For a Transfer, this is the account the money comes from. |
| To account | Transfer only — the destination account the money goes to. A transfer needs both a from and a to account, and the two must differ. |
| Description | Free text — what the entry is about. Useful at month-end. |
| Payment method | (More section) Free text — e.g. Maybank transfer, Cash |
| Tax code | (More section) SST / LHDN tax code if applicable |
Save creates a source = 'manual' transaction. Behind the scenes it also posts a balanced journal entry to the ledger — for a transfer, that's the money debited to the to account and credited from the from account — so the entry shows up in the trial balance and reports (see How Kiravy's general ledger works). A background AI deductibility check runs automatically and tags it for tax review.
The amount is always positive. Direction is carried by Type (income = money in, expense = money out, transfer = same-client movement). This matches mainstream accounting-software convention and keeps reports straightforward.
Editing and deleting
Open any transaction → all fields except workspace, client, and created by are editable. Those three are write-once to protect the audit trail.
To delete: Delete button at the bottom → confirm. This is a soft delete — the row is hidden from every list, filter, and search, but it isn't physically removed from the database. Recovery requires support.
Hard delete from the UI doesn't exist by design. Deleting tax-relevant data has 7-year retention implications in Malaysia.
Transactions migrated from SQL Account show a note on the detail page telling you where the row originally came from. That's just provenance — Kiravy is now the ledger of record. SQL Account is a one-time migration source, not a live system Kiravy syncs back to, so editing a migrated transaction simply updates it in Kiravy. There's no push-back to any source system; the change lives here.
The "Reviewed" workflow
When a senior accountant signs off on a row, they set reviewed_at on it. The list shows a green checkmark, and by default unreviewed entries float to the top of your view (because Unreviewed is the default filter).
Where does the review actually happen? Not on this tab directly — instead through the Month-end close Review queue, which is the bulk-review UI. Open an engagement, batch-tick a hundred rows at a time.
This is intentional: reviewing one row at a time on the Transactions tab would be tedious; the engagement workflow is built for closing a period systematically.
Sources, explained
Each transaction has an internal source tag (not displayed in the list, but visible on the detail page):
| Source | What it means |
|---|---|
| Manual | You typed it in via Add transaction |
| Receipt | Came from an OCR'd receipt. The receipt detail page links back to the original photo. |
| Integration | Synced from an accounting integration. The original external_id lets us de-dup on re-sync. |
| Bank | Imported from a bank statement / feed |
| CSV | Bulk-imported via the import wizard |
CSV import
For when you've got transactions in a spreadsheet that aren't worth re-typing. Import CSV button (next to Add transaction) opens a 4-step wizard at /clients/[clientId]/transactions/import:
- Upload — drag-drop the file. CSV or Excel. Kiravy AI suggests a column mapping based on header names.
- Mapping — confirm or adjust the mapping. You pick how amounts are encoded:
- Typed: separate
Amount+Typecolumns - Signed: one
Amountcolumn where positive = income, negative = expense - Debit/Credit: separate
DebitandCreditcolumns
- Typed: separate
- Preview — Kiravy shows you the parsed rows, with any errors highlighted, before anything is saved
- Done — confirmation with a count and a back-link to the list
Every imported row gets source = 'csv' and an internal import batch id so you can find them again if something goes wrong.
Date + amount fields are required (which amount columns depends on the mode you picked). Vendor, account code, description, and payment method are all optional.
Bulk edit
There isn't one — yet. Edit transactions one at a time on the detail page. The CSV import wizard lets you bulk create but not bulk update. A bulk-edit affordance is on the roadmap.
What each role sees
| Role | Permissions |
|---|---|
| Viewer (assigned) | Read-only list. Add transaction / Import CSV / Delete are hidden. Editing a transaction's form fields is disabled. |
| Staff (assigned) | Full read/write on assigned clients |
| Manager | Full read/write across every client in the firm |
| Partner | Same as Manager, plus firm-level admin |
Cross-firm access doesn't exist — RLS at the database level enforces tenant isolation.
What's next
- Receipts (OCR) — when transactions arrive as photos
- Month-end close — for the systematic review pass
- Chart of Accounts — how the account field actually works