;doc:balance:budget report: update/clean up

This commit is contained in:
Simon Michael 2023-12-07 18:48:26 -10:00
parent 9bad34c341
commit 0526c834dd

View File

@ -498,173 +498,157 @@ For reference, here is what the combinations of accumulation and valuation show:
### Budget report ### Budget report
The `--budget` report type activates extra columns showing any budget goals for each account and period. The `--budget` report type is like a regular balance report, but also shows budget goals and budget performance for each account and period.
The budget goals are defined by [periodic transactions](hledger.html#periodic-transactions).
This is useful for comparing planned and actual income, expenses, time usage, etc. This is useful for comparing planned and actual income, expenses, time usage, etc.
For example, you can take average monthly expenses in the common expense categories to construct a minimal monthly budget: [Periodic transaction rules](hledger.html#periodic-transactions) are used to define budget goals.
For example, here's a periodic transaction defining monthly goals for bus travel and food expenses:
```journal ```journal
;; Budget ;; Budget
~ monthly ~ monthly
income $2000 (expenses:bus) $30
expenses:food $400 (expenses:food) $400
expenses:bus $50 ```
expenses:movies $30
assets:bank:checking
After also recording some actual expenses,
```journal
;; Two months worth of expenses ;; Two months worth of expenses
2017-11-01 2017-11-01
income $1950 income $-1950
expenses:food $396 expenses:bus $35
expenses:bus $49 expenses:food:groceries $310
expenses:movies $30 expenses:food:dining $42
expenses:supplies $20 expenses:movies $38
assets:bank:checking assets:bank:checking
2017-12-01 2017-12-01
income $2100 income $-2100
expenses:food $412 expenses:bus $53
expenses:bus $53 expenses:food:groceries $380
expenses:gifts $100 expenses:food:dining $32
expenses:gifts $100
assets:bank:checking assets:bank:checking
``` ```
You can now see a monthly budget report: `hledger balance --budget` will show a budget report, like this:
```cli
$ hledger balance -M --budget
Budget performance in 2017/11/01-2017/12/31:
|| Nov Dec
======================++====================================================
assets || $-2445 [ 99% of $-2480] $-2665 [ 107% of $-2480]
assets:bank || $-2445 [ 99% of $-2480] $-2665 [ 107% of $-2480]
assets:bank:checking || $-2445 [ 99% of $-2480] $-2665 [ 107% of $-2480]
expenses || $495 [ 103% of $480] $565 [ 118% of $480]
expenses:bus || $49 [ 98% of $50] $53 [ 106% of $50]
expenses:food || $396 [ 99% of $400] $412 [ 103% of $400]
expenses:movies || $30 [ 100% of $30] 0 [ 0% of $30]
income || $1950 [ 98% of $2000] $2100 [ 105% of $2000]
----------------------++----------------------------------------------------
|| 0 [ 0] 0 [ 0]
```
This is different from a normal balance report in several ways. Currently:
- Accounts with budget goals during the report period, and their parents, are shown.
- Their subaccounts are not shown (regardless of the depth setting).
- Accounts without budget goals, if any, are aggregated and shown as "\<unbudgeted>".
- Amounts are always inclusive (subaccount-including), even in list mode.
- After each actual amount, the corresponding goal amount and percentage
of goal reached are also shown, in square brackets.
This means that the numbers displayed will not always add up!
Eg above, the `expenses` actual amount includes the gifts and supplies transactions,
but the `expenses:gifts` and `expenses:supplies` accounts are not
shown, as they have no budget amounts declared.
This can be confusing. When you need to make things clearer, use the `-E/--empty` flag,
which will reveal all accounts including unbudgeted ones, giving the full picture. Eg:
```cli ```cli
$ hledger balance -M --budget --empty $ hledger bal -M --budget
Budget performance in 2017/11/01-2017/12/31: Budget performance in 2017-11-01..2017-12-31:
|| Nov Dec || Nov Dec
======================++==================================================== ===============++============================================
assets || $-2445 [ 99% of $-2480] $-2665 [ 107% of $-2480] <unbudgeted> || $-425 $-565
assets:bank || $-2445 [ 99% of $-2480] $-2665 [ 107% of $-2480] expenses || $425 [ 99% of $430] $565 [131% of $430]
assets:bank:checking || $-2445 [ 99% of $-2480] $-2665 [ 107% of $-2480] expenses:bus || $35 [117% of $30] $53 [177% of $30]
expenses || $495 [ 103% of $480] $565 [ 118% of $480] expenses:food || $352 [ 88% of $400] $412 [103% of $400]
expenses:bus || $49 [ 98% of $50] $53 [ 106% of $50] ---------------++--------------------------------------------
expenses:food || $396 [ 99% of $400] $412 [ 103% of $400] || 0 [ 0% of $430] 0 [ 0% of $430]
expenses:gifts || 0 $100
expenses:movies || $30 [ 100% of $30] 0 [ 0% of $30]
expenses:supplies || $20 0
income || $1950 [ 98% of $2000] $2100 [ 105% of $2000]
----------------------++----------------------------------------------------
|| 0 [ 0] 0 [ 0]
``` ```
The budget report has two main differences compared to a normal balance report:
You can roll over unspent budgets to next period with `--cumulative`: - Goal amounts and performance percentages are also shown, in brackets after the actual amounts.
```cli
$ hledger balance -M --budget --cumulative
Budget performance in 2017/11/01-2017/12/31:
|| Nov Dec - Accounts which don't have budget goals (or subaccounts with goals) are grouped under "\<unbudgeted>" and not shown.
======================++====================================================
assets || $-2445 [ 99% of $-2480] $-5110 [ 103% of $-4960]
assets:bank || $-2445 [ 99% of $-2480] $-5110 [ 103% of $-4960]
assets:bank:checking || $-2445 [ 99% of $-2480] $-5110 [ 103% of $-4960]
expenses || $495 [ 103% of $480] $1060 [ 110% of $960]
expenses:bus || $49 [ 98% of $50] $102 [ 102% of $100]
expenses:food || $396 [ 99% of $400] $808 [ 101% of $800]
expenses:movies || $30 [ 100% of $30] $30 [ 50% of $60]
income || $1950 [ 98% of $2000] $4050 [ 101% of $4000]
----------------------++----------------------------------------------------
|| 0 [ 0] 0 [ 0]
```
It's common to limit budgets/budget reports to just expenses
```
hledger bal -M --budget expenses
```
or just revenues and expenses (eg, using account types):
```
hledger bal -M --budget type:rx
```
It's also common to limit or convert them to a single currency #### Using the budget report
(`cur:COMM` or `-X COMM [--infer-market-prices]`).
If showing multiple currencies, `--layout bare` or `--layout tall` can help.
For more examples and notes, see [Budgeting](/budgeting.html). This is a "goal-based budgeting" report; you define goals for accounts
and periods, often recurring, and hledger shows performance relative
to the goals. Contrast this with "envelope budgeting", which is more
detailed and strict - useful when cash is tight, but also quite a bit more work.
<https://plaintextaccounting.org/Budgeting> has more on this topic.
#### Budget report start date Historically this report has been confusing and fragile.
hledger's version is more robust than Ledger's, but bugs may still lurk.
Here are some more notes, to help with troubleshooting:
This might be a bug, but for now: - In the above example, `expenses:bus` and `expenses:food` are shown
when making budget reports, it's a good idea to explicitly set the because they have budget goals during the report period.
report's start date to the first day of a reporting period, because
a periodic rule like `~ monthly` generates its transactions on the 1st - Their parent `expenses` is also shown, with budget goals aggregated from the children.
of each month, and if your journal has no regular transactions on the 1st,
the default report start date could exclude that budget goal, which can - Their subaccounts `expenses:food:groceries` and `expenses:food:dining`
be a little surprising. Eg here the default report period is just the are not shown since they have no budget goal of their own,
day of 2020-01-15: but they contribute to `expenses:food`'s actual amount.
```journal - Unbudgeted accounts `expenses:movies` and `expenses:gifts` are also not shown,
~ monthly in 2020 but they contribute to `expenses`'s actual amount.
(expenses:food) $500
2020-01-15 - The other unbudgeted accounts `income` and `assets:bank:checking`)
expenses:food $400 are grouped as `<unbudgeted>`.
assets:checking
```
```cli
$ hledger bal expenses --budget
Budget performance in 2020-01-15:
|| 2020-01-15 - Amounts are always inclusive of subaccounts, even in `-l/--list` mode.
==============++============
<unbudgeted> || $400
--------------++------------
|| $400
```
To avoid this, specify the budget report's period, or at least the start date, - `--depth` or `depth:` can be used to limit report depth in the usual way,
with `-b`/`-e`/`-p`/`date:`, to ensure it includes the budget goal transactions but increasing the depth will not expose the unbudgeted subaccounts).
(periodic transactions) that you want. Eg, adding `-b 2020/1/1` to the above:
- Numbers displayed in a --budget report will not always agree with the totals,
because of hidden unbudgeted accounts; this is normal.
- Adding `-E` reveals the hidden accounts, which can make things clearer. Eg:
```cli ```cli
$ hledger bal expenses --budget -b 2020/1/1 $ hledger bal -M --budget -E
Budget performance in 2020-01-01..2020-01-15: Budget performance in 2017-11-01..2017-12-31:
|| 2020-01-01..2020-01-15 || Nov Dec
===============++======================== ===================================++==============================================
expenses:food || $400 [80% of $500] <unbudgeted> || $-425 $-565
---------------++------------------------ <unbudgeted>:assets:bank:checking || $1525 $1535
|| $400 [80% of $500] <unbudgeted>:income || $-1950 $-2100
expenses || $425 [ 99% of $430] $565 [131% of $430]
expenses:bus || $35 [117% of $30] $53 [177% of $30]
expenses:food || $352 [ 88% of $400] $412 [103% of $400]
expenses:food:dining || $42 $32
expenses:food:groceries || $310 $380
expenses:gifts || 0 $100
expenses:movies || $38 0
-----------------------------------++----------------------------------------------
|| 0 [ 0% of $430] 0 [ 0% of $430]
``` ```
It's common to restrict budget reports to just expenses, with a `expenses` or `type:x` query. Eg:
```cli
$ hledger bal -M --budget expenses
Budget performance in 2017-11-01..2017-12-31:
|| Nov Dec
===============++==========================================
expenses || $425 [ 99% of $430] $565 [131% of $430]
expenses:bus || $35 [117% of $30] $53 [177% of $30]
expenses:food || $352 [ 88% of $400] $412 [103% of $400]
---------------++------------------------------------------
|| $425 [ 99% of $430] $565 [131% of $430]
```
When you have multiple currencies, it's also useful to convert them to one (`-X COMM [--infer-market-prices]`),
and/or to show just one of them at a time (`cur:COMM`).
If you need to show multiple currencies at once, `--layout bare` can be helpful.
You can "roll over" amounts (actual and budgeted) to the next period with `--cumulative`:
```cli
$ hledger bal -M --budget expenses --cumulative
Budget performance in 2017-11-01..2017-12-31:
|| 2017-11-30 2017-12-31
===============++==========================================
expenses || $425 [ 99% of $430] $990 [115% of $860]
expenses:bus || $35 [117% of $30] $88 [147% of $60]
expenses:food || $352 [ 88% of $400] $764 [ 96% of $800]
---------------++------------------------------------------
|| $425 [ 99% of $430] $990 [115% of $860]
```
See also: <https://hledger.org/budgeting.html>.
#### Budgets and subaccounts #### Budgets and subaccounts
You can add budgets to any account in your account hierarchy. If you have budgets on both parent account and some of its children, then budget(s) You can add budgets to any account in your account hierarchy. If you have budgets on both parent account and some of its children, then budget(s)
@ -744,15 +728,61 @@ Budget performance in 2019/01:
|| 0 [ 0] || 0 [ 0]
``` ```
#### Selecting budget goals #### Budget date surprises
The budget report evaluates periodic transaction rules to generate special "goal transactions", With small data, or when starting out, you might run into this (possibly a UX bug):
which generate the goal amounts for each account in each report subperiod. the report start date [inferred by hledger](hledger.md#report-start--end-date) might exclude
When troubleshooting, you can use `print --forecast` to show these as forecasted transactions: some of the budget goal updates generated by [periodic rules](hledger.md#period-expressions).
```cli Eg with the following journal and report, the first period appears to have no expenses:food budget:
$ hledger print --forecast=BUDGETREPORTPERIOD tag:generated
```journal
~ monthly in 2020
(expenses:food) $500
2020-01-15
expenses:food $400
assets:checking
``` ```
```cli
$ hledger bal --budget expenses
Budget performance in 2020-01-15:
|| 2020-01-15
===============++====================
<unbudgeted> || $400
expenses:food || 0 [ 0% of $500]
---------------++--------------------
|| $400 [80% of $500]
```
The report heading(s) shows the report period.
In this case, it defaulted to just the 15th day of january,
including none of the budget goal updates which were generated on the 1st.
To fix this kind of thing, be more explicit about the report period (and/or the periodic rules' dates),
to make sure the report periods include your budget goal updates. In this case, adding `-b 2020` did the trick.
To see the budget goal updates, try replacing `bal --budget` with
`print --forecast tag:generated`, keeping the rest of the command the same. Eg:
```cli
$ hledger print --forecast expenses tag:generated
2020-02-01
(expenses:food) $500
2020-03-01
(expenses:food) $500
2020-04-01
(expenses:food) $500
...etc...
```
#### Selecting budget goals
By default, the budget report uses all available periodic transaction rules to generate goals. By default, the budget report uses all available periodic transaction rules to generate goals.
This includes rules with a different report interval from your report. This includes rules with a different report interval from your report.
Eg if you have daily, weekly and monthly periodic rules, Eg if you have daily, weekly and monthly periodic rules,
@ -762,43 +792,34 @@ You can select a subset of periodic rules by providing an argument to the `--bud
`--budget=DESCPAT` will match all periodic rules whose description contains DESCPAT, `--budget=DESCPAT` will match all periodic rules whose description contains DESCPAT,
a case-insensitive substring (not a regular expression or query). a case-insensitive substring (not a regular expression or query).
This means you can give your periodic rules descriptions This means you can give your periodic rules descriptions
(remember that [two spaces are needed](#two-spaces-between-period-expression-and-description)), (remember that [two spaces are needed](#two-spaces-between-period-expression-and-description) between period expression and description),
and then select from multiple budgets defined in your journal. and then select from multiple budgets defined in your journal.
#### Budget vs forecast #### Budgeting vs forecasting
`hledger --forecast ...` and `hledger balance --budget ...` are separate features, `--budget` and `--forecast` both use the periodic transaction rules in the journal to generate temporary transactions for reporting purposes.
though both of them use the periodic transaction rules defined in the journal, However they are separate features - though you can use both at the same time if you want.
and both of them generate temporary transactions for reporting purposes Here are some differences between them:
("forecast transactions" and "budget goal transactions", respectively).
You can use both features at the same time if you want.
Here are some differences between them, as of hledger 1.29:
CLI: 1. `--budget` is a command-specific option; it selects the **budget report**.
- --forecast is a general hledger option, usable with any command `--forecast` is a general option; **forecasting works with all reports**.
- --budget is a `balance` command option, usable only with that command.
Visibility of generated transactions: 2. `--budget` uses **all periodic rules**; `--budget=DESCPAT` uses **just the rules matched** by DESCPAT.
- forecast transactions are visible in any report, like ordinary transactions `--forecast` uses **all periodic rules**.
- budget goal transactions are invisible except for the goal amounts they produce in --budget reports.
Periodic transaction rules: 3. `--budget`'s budget goal transactions are invisible, except that they produce **goal amounts**.
- --forecast uses all available periodic transaction rules `--forecast`'s forecast transactions are visible, and **appear in reports**.
- --budget uses all periodic rules (`--budget`) or a selected subset (`--budget=DESCPAT`)
Period of generated transactions: 4. `--budget` generates budget goal transactions **throughout the report period**,
optionally restricted by periods specified in the periodic transaction rules.
- --forecast generates forecast transactions `--forecast` generates forecast transactions
- from after the last regular transaction to the end of the report period (`--forecast`) from **after the last regular transaction**, to the end of the report period;
- or, during a specified period (`--forecast=PERIODEXPR`) while `--forecast=PERIODEXPR` generates them **throughout the specified period**;
- possibly further restricted by a period specified in the periodic transaction rule both optionally restricted by periods specified in the periodic transaction rules.
- and always restricted within the bounds of the report period
- --budget generates budget goal transactions
- throughout the report period
- possibly restricted by a period specified in the periodic transaction rule.
### Balance report layout ### Balance report layout