Commit Graph

162 Commits

Author SHA1 Message Date
Simon Michael
bd0a45d448 fix:PeriodData: simplify, use Day keys [#2479]
This is clearer and slightly better-performing than using Integer.
2025-10-11 11:27:58 -10:00
Simon Michael
438c4a0469 fix:PeriodData: use Integer keys to avoid date wraparound bugs [#2479]
PeriodData's use of Int keys caused wrong results with periodic
reports involving dates outside the machine-specific limits of Int.
Those were:

64 bits: -25252734927764696-04-22..25252734927768413-06-12
32 bits: -5877752-05-08..5881469-05-27
16 bits:  1769-02-28..1948-08-04
 8 bits:  1858-07-12..1859-03-24

32 bits is supported by MicroHS; 16 and 8 bits aren't supported by
any known haskell version, but that could change in future.

For example, on 64 bit machines we got:

25252734927768413-06-12 PeriodData's max date
   (expenses)   1

25252734927768414-01-01 next year past PeriodData's max date
   (expenses)   2

$ hledger reg -O csv --yearly
"txnidx","date","code","description","account","amount","total"
"0","-25252734927764696-11-10","","","expenses","1","1"

Now it uses Integer (like the time package), fixing the bug.
And benchmarking shows memory and time usage slightly improved
(surprisingly; tested with up to 500 subperiods, eg
hledger -f examples/10ktxns-1kaccts.journal reg -1 cur:A -D >/dev/null)
2025-10-11 11:27:58 -10:00
Simon Michael
70e9e7b060 ;dev: lookupDayPartition -> dayPartitionFind 2025-10-11 11:02:18 -10:00
Stephen Morgan
b9caa4d948 dev!: balance: Use DayPartition for multibalance reports.
This allows us to guarantee that the report periods are well-formed and
don't contain errors (e.g. empty spans, spans not contiguous, spans not
a partition).

Note the underlying representation is now for disjoint spans, whereas
previously the end date of a span was equal to the start date of the
next span, and then was adjusted backwards one day when needed.
2025-10-09 15:31:28 -10:00
Simon Michael
2f007c93d2 dev: switch all qualifed imports to ImportQualifiedPost style 2025-09-29 19:28:59 -10:00
Stephen Morgan
f515c5f811 fix: balance: Don't display zero rows with --no-elide (#2454)
Zero rows with --no-elide should only be displayed if either --empty is
called or they have non-zero children at some depth.
2025-09-15 15:40:32 -07:00
Stephen Morgan
aad61e465d fix: balance: Correctly handle empty journals (#2452)
Eliminate several partial functions.
2025-09-11 07:29:27 +01:00
Simon Michael
bc55e1c58f dev: fix liftA2, Foldable1 build errors with ghc <9.6 [#2395] 2025-09-03 20:02:12 +01:00
Stephen Morgan
ef5c220690 fix: balance: Clip account names in generateMultiBalanceAccount, not before (#2434)
Previously accounts were clipped in getPostings, however compound
balance reports re-use the output of getPostings for the different
subreports. This caused a problem when clipping erased the information
needed to determine the account type, as would be used by e.g.
incomestatement.

Add some extra tests for --count.
2025-08-28 05:26:42 +01:00
Simon Michael
afd18a10bf fix: show historical balances even if report period is empty [#2403]
This adds a safer version of spanDefaultsFrom that won't create spans
that end before they start, and updates all reports to use it.

The only related change noticed so far is that close now gives an
error instead of a malformed entry, when there's no data to close.
[#2409]
2025-06-15 22:42:58 -10:00
Simon Michael
9c7e5b2467 dev:MultiBalanceReport: consistent debug output labels 2025-06-15 22:16:50 -10:00
Simon Michael
427a5de1f3 dev:MultiBalanceReport: use error' consistently for clean output 2025-06-15 22:06:34 -10:00
Stephen Morgan
80cf1d1995 !dev: lib: Allow Account to store date-indexed balances.
This upgrades Account to enable it to store a multiperiod balance, with
a separate balance for each date period. This enables it do the hard
work in MultiBalanceReport.

Some new types are created to enable convenient operation of accounts.
- `BalanceData` is a type which stores an exclusive balance, inclusive
  balance, and number of postings. This was previously directly stored
  in Account, but is now factored into a separate data type.
- `PeriodData` is a container which stores date-indexed data, as well as
  pre-period data. In post cases, this represents the report spans,
  along with the historical data.
- Account becomes polymorphic, allowing customisation of the type of
  data it stores. This will usually be `BalanceData`, but in
  `BudgetReport` it can use `These BalanceData BalanceData` to store
  both actuals and budgets in the same structure. The data structure
  changes to contain a `PeriodData`, allowing multiperiod accounts.

Some minor changes are made to behaviour for consistency:
- --declared treats parent accounts consistently.
- --flat --empty ensures that implied accounts with no postings are not displayed, but
  accounts with zero balance and actual postings are.
2025-06-04 23:10:00 -10:00
Stephen Morgan
74f0f37fb3 imp: queries: Allow regular expression depth queries
Previously depth-limiting was universal across all accounts, e.g. all
accounts are clipped to depth 2. However, sometimes you want certain
accounts clipped to a different depth than others, e.g. all expenses to
depth 3, while all assets to depth 2. This commit enables depth-limiting
to optionally include a regular expression, which limits the accounts it
applies to.

More than one depth limit can be passed, and they are applied to each
account name by the following rules:
- If one or more regular-expression depth limit applies, use the
  most specific one
- If no regular-expression depth limits apply, and a flat depth limit is
  supplied, use that
- Otherwise, do not do any depth limiting

For example, this will clip all accounts matching "assets" to depth 3,
all accounts matching "expenses" to depth 2, and all other accounts to
depth 1.
--depth assets=3 --depth expenses=2 --depth 1
2024-12-03 08:33:21 -10:00
Simon Michael
735beb96a7 imp:valuation: more compact and informative --debug=2 output [#2287]
Market prices are now shown using one line each,
the known prices are listed (forward / forward+reverse),
and the status of --infer-market-prices is shown.
2024-12-02 23:00:00 -10:00
Simon Michael
4e6f6611a6 dev: fix DisplayName's off-by-one indent value, noted in #2246
Now displayIndent (and prrIndent) 0 means no indent, 1 means one
indent step, etc.
2024-10-08 23:11:57 -10:00
Simon Michael
6ce5e85e99 dev: clarify: rename displayDepth/prrDepth to displayIndent/prrIndent
These are about indentation for rendering, not account depth;
these are not always directly related, eg when boring parents are elided.
2024-10-08 23:11:57 -10:00
Simon Michael
1a242c1264 dev: refactor table rendering code
- Consolidate some table rendering helpers in Balance.hs
- Rename, document for clarity
- Extract parameters for controlling table borders
- hlint suggestions
2024-06-12 05:01:48 +01:00
aragaer
09e158d31e fix: Fill totals with correct amount of zeroes for empty reports 2024-03-17 10:52:53 -10:00
Simon Michael
ca55c2f0f8 dev: rename other Price helpers to Cost
showAmountWithoutPrice             -> showAmountWithoutCost
mixedAmountStripPrices             -> mixedAmountStripCosts
showMixedAmountWithoutPrice        -> showMixedAmountWithoutCost
showMixedAmountOneLineWithoutPrice -> showMixedAmountOneLineWithoutCost
2024-01-23 21:35:06 -10:00
Simon Michael
323f87b3e9 dev: Amount: aprice -> acost
Acked-by: Simon Michael <simon@joyful.com>
2024-01-23 21:35:06 -10:00
Simon Michael
f8027abb44 dev:print: refactor, add AmountStyle "rounding strategy"
Changes to enable more control of "rounding" behaviour
(ie, choosing display precisions for amounts).

This reverts 1.31's change of asprecision, making it a non-Maybe
again, and adds a new asrounding field providing more control over how
a target display precision is applied to existing amounts (two options
for now, more later). Functionality is in an interim state (reports do
no rounding).
2023-10-18 13:56:24 +01:00
Simon Michael
97be1646f1 dev: AmountStyle: make setting the precision optional
This simplifies the code for styling amounts with or without precision.
But it complicates the semantics (Nothing is useful only when setting style).
Not sure if it's the best way.
2023-09-02 06:46:14 +01:00
Simon Michael
85845e51b2 dev: AmountStyle: rename, reorder fields more mnemonically
Since this type is about to change anyway.
2023-09-02 06:46:14 +01:00
Simon Michael
1be06c87c4 feat: bal: A new --count report type counts postings instead of amounts. 2023-04-20 14:36:41 -10:00
Simon Michael
fa70f160ae imp: partial/inferred dates are flexible, full dates are not (#1982)
DateSpans are now now aware of exact/flexible dates.
2023-02-17 07:24:19 -10:00
Simon Michael
c80c72d7cd dev: lib, cli, bin: enable/fix name shadowing warnings
And a few other cleanups.
2022-08-23 12:16:15 +01:00
Stephen Morgan
c966a0f413 fix!: cbr: Remove old account type query code. (#1921)
This replaces the old journal*AccountQuery with the new Type query. This
enables uniform treatment of account type, and fixes a subtle bug
(#1921).

Note that cbcsubreportquery no longer takes Journal as an argument.
2022-08-21 08:27:51 +01:00
Stephen Morgan
3e60e784f3 fix: bal: Allow cumulative gain and valuechange reports
Previously, --cumulative with --gain or --valuechange would produce an
empty report. This fixes this issue to produce a reasonable report.
2022-07-08 16:34:23 +01:00
Stephen Morgan
73925ae965 fix: types: Ensure auto postings can match against and be matched by type: queries.
This requires checking parent accounts for any new accounts introduced by auto postings which do not exist in the original journal.

Also refactor journalFinalise to only call journalPostingsAddAccountTags once, and use fewer intermediate variables.
2022-02-03 15:32:00 -10:00
Simon Michael
45127dc5f5 feat: new type: query for easy matching by account type
type:TYPES, where TYPES is any of the (case insensitive) letters
ALERXCV, matches accounts by their declared or inferred type.
(See https://hledger.org/hledger.html#account-types.)
This should work with most commands, eg:

    hledger bal type:al
    hledger reg type:x

API changes:

Journal has a new jaccounttypes map.
The journalAccountType lookup function makes it easy to check an account's type.
The journalTags and journalInheritedTags functions look up an account's tags.
Functions like journalFilterPostings and journalFilterTransactions,
and new matching functions matchesAccountExtra, matchesPostingExtra
and matchesTransactionExtra, use these to allow more powerful matching
that is aware of account types and tags.
2022-01-31 16:44:13 -10:00
Simon Michael
56be63e6f1 feat: queries can now match account tags (#1817)
Accounts, postings, and transactions can now all be filtered by the
tags in an account's declaration. In particular it's now possible to
more reliably select accounts by type, using their type: tag rather
than their name:

    account myasset       ; type:Asset
    account myliability   ; type:Liability

    $ hledger accounts tag:type=^a
    myasset

Accounts inherit tags from their parents.

API changes:
A finalised Journal has a new jdeclaredaccounttags field
for easy lookup of account tags.
Query.matchesTaggedAccount is a tag-aware version of matchesAccount.
2022-01-30 09:47:52 -10:00
Stephen Morgan
ba0eec9132 ref: Return the interval split in reportSpan, to reduce the number
of different places we call splitSpan and ease refactoring.
2022-01-26 08:05:37 -10:00
Stephen Morgan
8cd9e81c34 fix: budget: Make sure boring parents of unbudgeted accounts are not
elided if they have a budget. (#1800)

This only affects calls with --budget and -E, but not with --no-elide.
2022-01-21 09:11:04 -10:00
Stephen Morgan
8eedbbbe87 imp: cost: Generate totally balanced conversion postings for amounts with costs.
Introduce --infer-equity option which will generate conversion postings.
--cost will override --infer-equity.

This means there will no longer be unbalanced transactions, but will be
offsetting conversion postings to balance things out. For example.

2000-01-01
  a   1 AAA @@ 2 BBB
  b  -2 BBB

When converting to cost, this is treated the same as before.
When used with --infer-equity, this is now treated as:

2000-01-01
  a                               1 AAA
  equity:conversion:AAA-BBB:AAA  -1 AAA
  equity:conversion:AAA-BBB:BBB   2 BBB
  b                              -2 BBB

There is a new account type, Conversion/V, which is a subtype of Equity/E.
The first account declared with this type, if any, is used as the base account
for inferred equity postings in conversion transactions, overriding the default
"equity:conversion".

API changes:

Costing has been changed to ConversionOp with three options:
NoConversionOp, ToCost, and InferEquity.
The first correspond to the previous NoCost and Cost options, while the
third corresponds to the --infer-equity flag.  This converts transactions with costs
(one or more transaction prices) to transactions with equity:conversion postings.
It is in ConversionOp because converting to cost with -B/--cost and inferring conversion
equity postings with --infer-equity are mutually exclusive.

Correspondingly, the cost_ record of ReportOpts has been changed to
conversionop_.

This also removes show_costs_ option in ReportOpts, as its functionality
has been replaced by the richer cost_ option.
2021-12-21 10:50:13 -10:00
Simon Michael
d1a0d37bd1 fix: bal: --declared now respects not:ACCT (fix #1783) 2021-12-09 12:58:22 -10:00
Stephen Morgan
3884f90cc6 lib!: Rename CommodityLayout to Layout and rename constructors.
Their scope is more than just commodities.
2021-12-05 16:06:44 -10:00
Simon Michael
7e47d36451 ;cln: typo 2021-11-25 11:55:58 -10:00
Simon Michael
7f320ebfa9 imp: balcmds: support --declared on bs/cf/is also (#1765) 2021-11-25 11:55:58 -10:00
Simon Michael
6319d6148f feat: bal: with --declared, include declared leaf accounts (#1765)
Together with -E, this shows a balance for both used and declared
accounts (excluding empty parent accounts, which are usually not
wanted in list-mode reports).

This is somewhat consistent with --declared in the accounts and payees
commands, except for the leaf account restriction.

The idea of this is to be able to see a useful "complete" balance
report, even when you don't have transactions in all of your declared
accounts yet. I mainly want this for hledger-ui, but there's no harm
in exposing it in the balance CLI as well.
2021-11-23 09:47:04 -10:00
Simon Michael
94d92b9760 Revert "feat: bal: with --declared, include all declared accounts (#1765)"
This reverts commit a5e19b7391.
(It breaks filtering by account.)
2021-11-22 12:06:23 -10:00
Simon Michael
a5e19b7391
feat: bal: with --declared, include all declared accounts (#1765)
Together with -E, this allows showing a balance for all accounts, both
used and declared. I mainly want this for hledger-ui, but there's no
harm in exposing it in the balance command as well. This is somewhat
consistent with the accounts and payees commands.
2021-11-22 11:08:33 -10:00
Stephen Morgan
186995fc8b fix: balance: Balance reports with --depth=0 should report on true
values, not zero everywhere. (#1761)
2021-11-20 15:47:57 -10:00
Stephen Morgan
d82416b7b9 imp: balance: Add single-line display with elision back in, this time
with a separate option --layout=wide,WIDTH.
2021-11-18 21:26:02 -10:00
Stephen Morgan
7e21f05a83 imp: balance: Implement multi-line display for multicommodity balance reports.
This allows more control over how multicommodity amounts are displayed.
In addition to the default single-line display, and the recent commodity
column display, we now have multi-line display. This is controlled by
the --layout option, which has possible values "wide", "tall", and
"bare". The --commodity-column option has been hidden, but is equivalent
to --layout=bare.

squash
2021-11-18 21:26:02 -10:00
Simon Michael
b4c1188c26 ref!: postingDateOrDate2, transactionDateOrDate2, whichDateFromOpts -> whichDate (#1731) 2021-10-10 10:34:35 -10:00
Stephen Morgan
5aadcdea4d ref: Add new helper functions journalValueAndFilterPostings(With)?.
Combining valuation with filtration is subtle and error-prone (see e.g. #1625).
We have to do in in both MultiBalanceReport and PostingsReport, where it
is done in slightly different ways. This refactors this functionality
into separate functions which are called in both reports, for uniform
behaviour.
2021-09-26 08:13:12 -10:00
Stephen Morgan
bf3e82f780 imp: pretty: Replace --pretty-tables argument with --pretty=WHEN
argument, which takes yes or no. Default is no for now.
2021-09-21 14:53:52 -10:00
Stephen Morgan
1e766e481e cln: Flatten dependency tree by removing dependencies of Hledger.Reports
on Hledger.Read.

This is done by using equivalent functions/types defined elsewhere
instead.
2021-09-19 17:10:38 -10:00
Stephen Morgan
a2d7ac5318 ref: balance: Refactor getPostingsByColumn to use groupByDateSpan.
This reduces code duplication, makes the code more idiomatic, and hides
optimisation magic within groupByDateSpan.
2021-09-18 14:40:28 -10:00