Gallery › Money › Money transactions (illustrative)
Money transactions (illustrative)
Transactions grouped by kind and category, a table with a sum per category, the same rows by entity, and a form that recategorises one. Illustrative rows only: money's synthetic test fixture, never real account data.
The .base file and its data
Every tab above is one entry of this file; the views read these rows. ⋯ in the toolbar copies the current view as YAML.
# Transactions, ILLUSTRATIVE: money's test fixture (synthetic rows, no real account data), each booked by money's own
# ledger code. Obsidian Bases grammar plus data-ui's keys (docs/CONTRACT.md §5).
data: transactions.json
facets:
- entity
- group
- category
views:
- type: list
name: Recent
order: [name, amount, date, entity]
groupBy: { property: group, direction: ASC }
subGroupBy: { property: category, direction: ASC }
sort:
- { property: date, direction: DESC }
markers: none
separator: " · "
- type: table
name: By category
order: [name, date, amount, entity, account, how]
groupBy: { property: category, direction: ASC }
sort:
- { property: date, direction: DESC }
summaries: { amount: Sum }
- type: list
name: By entity
order: [name, amount, date, category]
groupBy: { property: entity, direction: ASC }
subGroupBy: { property: group, direction: ASC }
sort:
- { property: date, direction: DESC }
markers: number
- type: record
name: Categorise
filters: 'group != "Transfers"'
edit: true
record:
sections:
- { name: Transaction, properties: [date, amount, entity, account, merchant, plaid] }
- { name: Category, properties: [category, group, how] }
// transactions.json: 19 rows, 10 KB; the first 3
{
"id": "money-transactions-illustrative",
"title": "Transactions (illustrative: money's test fixture)",
"titleProperty": "name",
"source": "ILLUSTRATIVE: ~/money/tests/acceptance/fixture_home (synthetic), booked by money's src/money/ledger.py; no real account data",
"properties": {
"name": {
"type": "text",
"label": "Description",
"readOnly": true
},
"date": {
"type": "date",
"label": "Date",
"readOnly": true
},
"entity": {
"type": "text",
"label": "Entity",
"display": "badge",
"readOnly": true,
"colors": {
"bam": 1,
"personal": 5
}
},
"account": {
"type": "text",
"label": "Bank account",
"readOnly": true
},
"merchant": {
"type": "text",
"label": "Merchant",
"readOnly": true
},
"amount": {
"type": "number",
"label": "Amount",
"unitText": "CAD",
"decimals": 2,
"readOnly": true,
"note": "money in positive, money out negative"
},
"currency": {
"type": "text",
"label": "Currency",
"hidden": true,
"readOnly": true
},
"category": {
"type": "text",
"label": "Category",
"constraints": {
"enum": [
"Equity:Transfers",
"Expenses:Entertainment",
"Expenses:Fees",
"Expenses:Food",
"Expenses:Government",
"Expenses:Health",
"Expenses:Housing",
"Expenses:Loan-Payments",
"Expenses:Other",
"Expenses:Payroll",
"Expenses:Purchases",
"Expenses:Services",
"Expenses:Transport",
"Expenses:Travel",
"Income:Interest",
"Income:Investment",
"Income:Other",
"Income:Revenue",
"Income:Salary"
]
},
"note": "the ledger account money books it to; fix one with a rules.toml rule"
},
"group": {
"type": "text",
"label": "Kind",
"display": "badge",
"derived": "the category's top level; a transfer between own accounts, or to Equity:Transfers, is Transfers",
"colors": {
"Expenses": 2,
"Income": 3,
"Transfers": 0
}
},
"how": {
"type": "text",
"label": "Categorised by",
"derived": "money's precedence: rule, matched transfer, Plaid category"
},
"plaid": {
"type": "text",
"label": "Plaid category",
"readOnly": true
},
"transfer_pair": {
"type": "boolean",
"label": "Between own accounts",
"hidden": true,
"readOnly": true
}
},
"rows": [
{
"id": "tx-p-10",
"date": "2026-10-13",
"entity": "personal",
"account": "Assets:Cash:RBC-Royal-Bank:RBC-Day-to-Day-Banking-1234",
"name": "E-TRANSFER TO MISA",
"merchant": null,
"amount": -200,
"currency": "CAD",
"category": "Equity:Transfers",
"group": "Transfers",
"how": "unmatched transfer",
"plaid": "TRANSFER_OUT_ACCOUNT_TRANSFER",
"transfer_pair": false
},
{
"id": "tx-p-06",
"date": "2026-10-12",
"entity": "personal",
"account": "Assets:Cash:RBC-Royal-Bank:RBC-Day-to-Day-Banking-1234",
"name": "SAFEWAY #4402",
"merchant": "Safeway",
"amount": -85.2,
"currency": "CAD",
"category": "Expenses:Food",
"group": "Expenses",
"how": "Plaid FOOD_AND_DRINK",
"plaid": "FOOD_AND_DRINK_GROCERIES",
"transfer_pair": false
},
{
"id": "tx-a-05",
"date": "2026-10-11",
"entity": "personal",
"account": "Liabilities:CreditCard:American-Express:Amex-Cobalt-1005",
"name": "CANADIAN TIRE #123",
"merchant": "Canadian Tire",
"amount": -120,
"currency": "CAD",
"category": "Expenses:Purchases",
"group": "Expenses",
"how": "Plaid GENERAL_MERCHANDISE",
"plaid": "GENERAL_MERCHANDISE_OTHER_GENERAL_MERCHANDISE",
"transfer_pair": false
}
]
}README.md
# Money transactions (illustrative)
Transactions grouped by kind and category, a table with a sum per category, the same rows by entity, and a form that
recategorises one. **Illustrative rows only:** money's synthetic test fixture, never real account data.
- **App:** Money
- **Replaces:** money has no transaction list of its own: its Flask pages (`statements.html` and `home.html` in
`~/money`, `src/money/templates`) show totals by category, and the transactions themselves are only in Fava's journal.
This is the list those totals come from, grouped the way the statements group them, with the category as a field
you can propose a change to (money's own fix is a rule in `rules.toml`).
- **Shows:** `type: list` with `groupBy` + `subGroupBy` (kind -> category) and numbered markers, a table grouped by
category with Sum summaries (view summaries, from the rows), and `type: record` with `edit: true`: the category is
a select over money's account list (`constraints.enum`), everything the bank reported is read-only. On this static
page the host refuses the save, and says so.
- **Data:** `transactions.json`, 19 rows written by `source/make.py` from `tests/acceptance/fixture_home` in `~/money`
(synthetic: ACME WASTE, account masks 9001 and 1234), booked by money's `src/money/ledger.py` (rules first, then
matched transfers, then Plaid's category). Amounts are CAD, money in positive.
The original UI it replaces
money has no transaction list of its own: its Flask pages (statements.html and home.html in ~/money, src/money/templates) show totals by category, and the transactions themselves are only in Fava's journal. This is the list those totals come from, grouped the way the statements group them, with the category as a field you can propose a change to (money's own fix is a rule in rules.toml).
What it shows
type: list with groupBy + subGroupBy (kind -> category) and numbered markers, a table grouped by category with Sum summaries (view summaries, from the rows), and type: record with edit: true: the category is a select over money's account list (constraints.enum), everything the bank reported is read-only. On this static page the host refuses the save, and says so.
Data
transactions.json, 19 rows written by source/make.py from tests/acceptance/fixture_home in ~/money (synthetic: ACME WASTE, account masks 9001 and 1234), booked by money's src/money/ledger.py (rules first, then matched transfers, then Plaid's category). Amounts are CAD, money in positive.