Compare commits

...

22 Commits

Author SHA1 Message Date
Simon Michael
f02a4b7359 fix: web: add form's typeahead now shows non-ascii text correctly (#1961)
Some checks failed
binaries-windows-x64 / build (push) Has been cancelled
binaries-mac-x64 / build (map[ghc:92 stack:stack --stack-yaml=stack.yaml]) (push) Has been cancelled
(Fix contributed by Arsen Arsenović)
2025-10-14 11:40:42 +03:00
f81cc8a5fe Translate to Finnish 2025-10-14 11:40:42 +03:00
Simon Michael
aa327b7a4b ;cabal: update cabal files 2022-09-18 08:57:59 -10:00
Simon Michael
c679d184a9 ;pkg: bump version to 1.27.1 2022-09-18 08:57:59 -10:00
Simon Michael
e250b03cc0 install: 1.27.1 2022-09-18 08:51:14 -10:00
Simon Michael
06989eb867 dev: cli: tests: fix fragile abbreviation 2022-09-18 08:37:31 -10:00
Simon Michael
fc858d1159 fix: balcmds: fix empty html columns fix (#1933) 2022-09-18 08:37:28 -10:00
Simon Michael
0c179c7e28 dev: lib: ReportTypes: hlint fix 2022-09-18 08:37:26 -10:00
Simon Michael
7102d6f9e8 fix: balcmds: handle an empty totals column in html output (#1933) 2022-09-18 08:37:20 -10:00
Simon Michael
1d191d13ae dev: cli: update balance.test to v3 format 2022-09-18 08:37:18 -10:00
Simon Michael
55b59913d7 dev: web: start also tracking manual hledger-web tests
related: #1932
2022-09-18 08:37:14 -10:00
Simon Michael
599264b212 fix: web: add: don't fail when there's no file field (#1932) 2022-09-18 08:37:05 -10:00
Simon Michael
3411949313 doc: RELEASING: updates 2022-09-18 08:36:21 -10:00
Simon Michael
e2d517a310 doc: RELEASING: updates 2022-09-18 08:36:19 -10:00
Simon Michael
c561b9859f doc: cli: changelog: fixes 2022-09-18 08:36:15 -10:00
Simon Michael
779c73a906 doc: update github release links 2022-09-01 17:28:18 -07:00
Simon Michael
732e43d6af install: 1.27 2022-09-01 17:28:04 -07:00
Simon Michael
fe58ce7484 ;doc: announce 2022-09-01 17:22:05 -07:00
Simon Michael
a0be6c2c85 doc: update changelogs 2022-09-01 16:06:36 -07:00
Simon Michael
705280283c ;doc: update manuals 2022-09-01 16:06:05 -07:00
Simon Michael
9cb04480b5 ;cabal: update cabal files 2022-09-01 16:00:38 -07:00
Simon Michael
45f1f44498 ;pkg: bump version to 1.27 2022-09-01 16:00:38 -07:00
62 changed files with 2841 additions and 2643 deletions

View File

@ -1 +1 @@
1.26.99 1.27.1

View File

@ -9,12 +9,14 @@
General changes in the hledger project. General changes in the hledger project.
For package-specific changes, see the hledger package changelogs. For package-specific changes, see the hledger package changelogs.
# 991e5a836 # 1.27 2022-09-01
Docs Docs
- https://hledger.org/ERRORS.html - an overview of hledger's error messages. - https://hledger.org/ERRORS.html - an overview of hledger's error messages.
- Rewrite/consolidate cost and conversion docs.
- New template for github releases, with improved install instructions for binaries. - New template for github releases, with improved install instructions for binaries.
- Add modern windows binary install instructions. (Lazar Lazarov, Simon Michael) - Add modern windows binary install instructions. (Lazar Lazarov, Simon Michael)

View File

@ -79,37 +79,57 @@ Here are some definitions, useful eg when executing or automating release proced
| *master* | The branch named `master` in the hledger repo; the main line of hledger development. Pull requests are usually relative to this. | | *master* | The branch named `master` in the hledger repo; the main line of hledger development. Pull requests are usually relative to this. |
| *release branch* | Branches named `MA.JOR-branch` in the hledger repo, eg `1.25-branch`. Releases and release previews are always made from a release branch. | | *release branch* | Branches named `MA.JOR-branch` in the hledger repo, eg `1.25-branch`. Releases and release previews are always made from a release branch. |
## Activities
Release manager activities/responsibilities include:
- **Software** - selecting changes, packages, release dates; coordinating contributions; ensuring release readiness
- **Branch Management** - coordinating main and release branch, local and remote repos, CI branches
- **Version Bumping** - choosing and applying new version numbers and related things like tags, github releases, urls, ghc and dep versions, stackage resolvers, everywhere needed
- **Docs** - command help, manuals, changelogs, release notes, github release notes, install page, install scripts, announcements, process docs
- **Testing** - local testing, CI testing, extra release-specific testing
- **Artifacts** - generating binaries, zip files, github releases etc.
- **Publishing** - uploading, pushing, making visible, finalising
- **Announcing** - various announcement stages and channels
These have complex interdependencies and sequencing constraints. Chunk, separate, routinise, document and automate them as far as possible.
## General tips
- Update changelogs early and often, eg during/after a PR, to spread the work.
See also [CHANGELOGS](CHANGELOGS.html).
- Release (or practice releasing) often.
- Follow RELEASING.md's procedures if helpful. Update a copy (RELEASING2.md) while releasing.
- The release process continually evolves. Don't document procedures in too much detail / prematurely.
- Make things a little better each time through: simpler, more reliable, better documented, more automated, easier, faster, cheaper, higher quality.
- Make releases from a release branch, not from master. Use the tools/release script.
- Before publishing a github release: prepare binaries, release notes, announcements, and tag.
- Before tagging: make binaries for all platforms, from the same commit.
- Before making binaries: do all possible pre-tagging steps and try to get everything finalised. (Binaries' --version shows their git hash, and this should match the release tag.)
## Procedures ## Procedures
### 0. General tips ### Do a release
- Release (or practice releasing) often. - save RELEASING.md as RELEASING2.md
- Release responsibilities include:
- **Software** - selecting changes, packages, release dates; coordinating contributions; ensuring release readiness
- **Branch Management** - coordinating main and release branch, local and remote repos, CI branches
- **Version Bumping** - choosing and applying new version numbers and related things like tags, github releases, urls, ghc and dep versions, stackage resolvers, everywhere needed
- **Docs** - command help, manuals, changelogs, release notes, github release notes, install page, install scripts, announcements, process docs
- **Testing** - local testing, CI testing, extra release-specific testing
- **Artifacts** - generating binaries, zip files, github releases etc.
- **Publishing** - uploading, pushing, making visible, finalising
- **Announcing** - various announcement stages and channels
- These have complex interdependencies and sequencing constraints. Chunk, separate, routinise, document and automate them as far as possible.
- Don't document in too much detail prematurely.
- Follow RELEASING.md's procedures when helpful, ignore them when not.
- As step 1, save it as RELEASING2.md and make changes there until after release.
- Make things a little better each time through: simpler, more reliable, better documented, more automated, easier, faster, cheaper, higher quality.
- Update [CHANGELOGS](CHANGELOGS.html) early and often, eg during/after a PR, to spread the work.
- Make releases from a release branch, not from master.
- Before making binaries: try to do all possible pre-release-tag steps. (Binaries' --version shows their git hash, and it should match the release tag.)
- Before tagging: make binaries for all platforms, from the same commit.
### 1. Preview release
- [check release readiness](#check-release-readiness) - [check release readiness](#check-release-readiness)
- [prepare release branch](#prepare-release-branch) - start making draft binaries: push to `origin/binaries`, resolve failures
- [make binaries](#make-binaries) - update changelogs: see CHANGELOGS.md
- [make release notes](#make-release-notes)
- choose version: MA.JOR, MA.JOR.MINOR, or MA.JOR.MINOR.FIXUP
- [prepare release branch](#prepare-release-branch) (preview/major release)
or cherry pick changes from master (bugfix/fixup release)
- [make new manuals](#make-new-manuals) (major release)
- [update hledger-install](#update-hledger-install) (major/bugfix/fixup release)
- [update install page](#update-install-page) (major/bugfix/fixup release)
- [make announcement](#make-announcement) (major/bugfix release)
- [tag the release](#tag-the-release) - [tag the release](#tag-the-release)
- [push to github](#push-to-github) - [make release binaries](#make-release-binaries)
- [make github release](#make-github-release) - [make github release](#make-github-release) draft
- [update master from release branch](#update-master-from-release-branch) - upload to hackage: `make hackageupload` (major/bugfix/fixup release)
- publish github release
- publish website changes: manuals, release notes, install page
- [announce release](#announce-release) (major/bugfix release)
- move RELEASING2 updates back to RELEASING, commit
- [cherry-pick release branch to master](#cherry-pick-release-branch-to-master)
- bump master to next version: `./Shake setversion A.BB.99` (major release)
#### Check release readiness #### Check release readiness
- master's changelogs are up to date (see [CHANGELOGS](CHANGELOGS.html)) - master's changelogs are up to date (see [CHANGELOGS](CHANGELOGS.html))
@ -124,6 +144,20 @@ Here are some definitions, useful eg when executing or automating release proced
- commit any changes (msg: `tools: shake`) - commit any changes (msg: `tools: shake`)
- appropriate timing, release manager availability - appropriate timing, release manager availability
#### Make release notes
In site repo:
- update `src/release-notes.md`
- copy template, uncomment
- replace date
- replace XX with NEW
- add new changelog sections, excluding hledger-lib
- remove any empty sections
- add contributors, `git shortlog -sn OLD..NEW`
- add summary (major release) or remove it (bugfix release)
- check preview in vs code
- commit: `relnotes: NEW`
#### Prepare release branch #### Prepare release branch
- `PAUSE=1 ECHO=1 tools/release prep MA.JOR[.99.PREVIEWNUM]` (eg 1.24.99.1 for 1.25 preview 1) - `PAUSE=1 ECHO=1 tools/release prep MA.JOR[.99.PREVIEWNUM]` (eg 1.24.99.1 for 1.25 preview 1)
(XXX seems to go wrong without PAUSE`) (XXX seems to go wrong without PAUSE`)
@ -144,65 +178,14 @@ Here are some definitions, useful eg when executing or automating release proced
- `stack exec -- hledger --version`, check version - `stack exec -- hledger --version`, check version
- `stack exec -- hledger help | tail`, check version & date - `stack exec -- hledger help | tail`, check version & date
#### Make binaries #### Make new manuals
- `tools/release bin`
- get all platforms built on the same commit
- download binary artifact zip files
#### Tag the release
- `make tag`
#### Push to github
- `git push origin MA.JOR-branch && git push --tags`
- or in magit: `P p`, `P t`
#### Make github release
- copy text from previous similar release, https://github.com/simonmichael/hledger/releases
- create new release, https://github.com/simonmichael/hledger/releases/new
- select release tag (MA.JOR[...])
- set title (MA.JOR[...])
- paste & replace with new release notes
- upload CI binaries
- save as draft
- github release testing (preview)
- publish
#### Update master from release branch
- switch back to master
- update master changelogs, merging final release changelog entries (see [CHANGELOGS](CHANGELOGS.html))
- cherry-pick other useful changes, such as `;doc: ANNOUNCE`
- after a major release: bump master to new dev version (`./Shake setversion -c A.B.99`)
### 2. Major release
- [make release notes](#make-release-notes)
- [make announcement](#make-announcement)
- [update hledger-install](#update-hledger-install)
- prepare as for [preview release](#1-preview-release)
- [update install page](#update-install-page)
- [add manuals to website](#add-manuals-to-website)
- [announce major release](#announce-major-release)
#### Make release notes
In site repo: In site repo:
- update `src/release-notes.md` - js/site.js: add NEW, update currentrelease
- copy template, uncomment - Makefile: add NEW, two places
- replace date - make snapshot-NEW (after ensuring main repo has been release-tagged)
- replace XX with NEW - commit: `current, makefile, site.js: NEW`
- add new changelog sections, excluding hledger-lib - push
- remove any empty sections
- add contributors, `git shortlog -sn OLD..NEW`
- add summary (major release) or remove it (bugfix release)
- check preview in vs code
- commit: `relnotes: NEW`
#### Make announcement
In release branch:
- update `doc/ANNOUNCE` (major release)
- summary, contributors from release notes
- any other edits
- commit: `;doc: announce`
#### Update hledger-install #### Update hledger-install
- update `hledger-install/hledger-install.sh` - update `hledger-install/hledger-install.sh`
@ -230,16 +213,35 @@ In site repo:
- Total count from `make functest` - Total count from `make functest`
- commit: `download: NEW` - commit: `download: NEW`
#### Add new manuals to website #### Make announcement
In site repo: In release branch:
- js/site.js: add NEW, update currentrelease - update `doc/ANNOUNCE` (major release)
- Makefile: add NEW, two places - summary, contributors from release notes
- make snapshot-NEW (after ensuring main repo has been release-tagged) - any other edits
- commit: `makefile, js: update for NEW` - commit: `;doc: announce`
- push
#### Announce major release #### Tag the release
- `make tag`
#### Make release binaries
- `tools/release bin`
- get all platforms built on the same commit
- download binary artifact zip files
#### Make github release
- `git push origin MA.JOR-branch && git push --tags` (or magit `P p`, `P t`)
- copy text from previous similar release, https://github.com/simonmichael/hledger/releases
- create new release, https://github.com/simonmichael/hledger/releases/new
- select release tag (MA.JOR[...])
- set title (MA.JOR[...])
- paste & replace with new release notes
- upload CI binaries
- save as draft
- github release testing: preview on github, upload to hackage
- publish
#### Announce release
- pause; take a break afk; check time and energy - pause; take a break afk; check time and energy
- push main repo - push main repo
- push site repo - push site repo
@ -263,17 +265,13 @@ In site repo:
- update last release date on plaintextaccounting.org - update last release date on plaintextaccounting.org
<!-- - toot at https://fosstodon.org/web/accounts/106304084994827771 ? --> <!-- - toot at https://fosstodon.org/web/accounts/106304084994827771 ? -->
### 3. Fixup release #### Cherry-pick release branch to master
- switch to release branch - switch back to master
- cherry pick changes from master - update master changelogs, merging final release changelog entries (see [CHANGELOGS](CHANGELOGS.html))
- proceed as above, with MA.JOR.MINOR.FIXUP - cherry-pick other useful changes, such as `;doc: ANNOUNCE`
- after a major release: bump master to new dev version (`./Shake setversion -c A.B.99`)
### 4. Bugfix release ### Do post-release followup
- switch to release branch
- cherry pick changes from master
- proceed as above, with MA.JOR.MINOR
### 5. After a release
- monitor packaging status, update install page - monitor packaging status, update install page
- docker - expect/merge PR - docker - expect/merge PR
- homebrew - expect badge to update soon - homebrew - expect badge to update soon
@ -283,7 +281,7 @@ In site repo:
- prepare followup releases if needed - prepare followup releases if needed
- update process docs and tools - update process docs and tools
### Packaging ### Update packaging
#### Update homebrew formula #### Update homebrew formula

View File

@ -1,29 +1,38 @@
Aloha! I am pleased to announce hledger 1.26: I'm pleased to announce hledger 1.27 !
https://github.com/simonmichael/hledger/releases/1.26 https://github.com/simonmichael/hledger/releases/1.27
https://hledger.org/install https://hledger.org/install
https://hledger.org/release-notes.html#hledger-1-26 https://hledger.org/release-notes.html#hledger-1-27
1.26 is a modest maintenance release; highlights include Highlights include inferring costs from equity postings,
faster register reports and clearer error messages. new error checks, and improved error messages.
Thank you to core contributor Stephen Morgan. Thank you to release contributors
Stephen Morgan,
Alex Hirzel,
Pranesh Prakash,
David D Lowe,
Charlotte Van Petegem,
Max Thomas,
Andrew Lelechenko.
What is hledger ? What is hledger ?
- free, high quality Plain Text Accounting[1] software: - Fast, reliable, free, multicurrency, double-entry, plain text
- a fast and robust multicurrency double-entry accounting system accounting[1] software that runs on unix, mac, windows, and the web
- built around human-readable, version-controllable plain text files
- inspired by and partly compatible with Ledger CLI[2]
- convertible to and from Beancount[3]
- written in Haskell for correctness and longevity
- easy to install on unix, mac and windows.
For help getting started, or more info, see https://hledger.org, - Built around human-readable, version-controllable plain text files
and join our chat via Matrix or IRC: https://hledger.org/support.
Newcomers, experts, contributors, sponsors, feedback are always welcome!
Best wishes, - Inspired by and largely compatible with Ledger CLI[2];
convertible to and from Beancount[3]
- Written in Haskell for correctness and longevity.
For help getting started, or more info, see https://hledger.org
and join our chat via Matrix or IRC: https://hledger.org/support
Newcomers, experts, contributors, sponsors, feedback are welcome!
Aloha,
-Simon -Simon

View File

@ -119,12 +119,8 @@ Problems:
</details> </details>
## Next steps ## Next steps
Once installed, you could try these quick starts / tutorials:
- https://hledger.org/index.html#how-to-get-started - [Getting Started](https://hledger.org/start.html)
- https://hledger.org/add.html
- https://hledger.org/ui.html
- https://hledger.org/web.html
<!-- <!--

View File

@ -46,7 +46,7 @@ HERE
HLEDGER_INSTALL_TOOL=hledger-install.sh HLEDGER_INSTALL_TOOL=hledger-install.sh
# this script's version # this script's version
HLEDGER_INSTALL_VERSION=20220711 HLEDGER_INSTALL_VERSION=20220918
# stackage snapshot to use when installing with stack. # stackage snapshot to use when installing with stack.
# You can try specifying a different stackage version here, or # You can try specifying a different stackage version here, or
@ -70,10 +70,10 @@ hledger-stockquotes \
# Latest hledger package versions. # Latest hledger package versions.
# Don't forget to also bump HLEDGER_INSTALL_VERSION above. # Don't forget to also bump HLEDGER_INSTALL_VERSION above.
HLEDGER_LIB_VERSION=1.26.1 HLEDGER_LIB_VERSION=1.27.1
HLEDGER_VERSION=1.26.1 HLEDGER_VERSION=1.27.1
HLEDGER_UI_VERSION=1.26.1 HLEDGER_UI_VERSION=1.27.1
HLEDGER_WEB_VERSION=1.26.1 HLEDGER_WEB_VERSION=1.27.1
# addons: # addons:
HLEDGER_IADD_VERSION=1.3.17 HLEDGER_IADD_VERSION=1.3.17
HLEDGER_INTEREST_VERSION=1.6.4 HLEDGER_INTEREST_VERSION=1.6.4

View File

@ -1,2 +1,2 @@
m4_dnl Date to show in man pages. Updated by "Shake manuals" m4_dnl Date to show in man pages. Updated by "Shake manuals"
m4_define({{_monthyear_}}, {{August 2022}})m4_dnl m4_define({{_monthyear_}}, {{September 2022}})m4_dnl

View File

@ -1 +1 @@
1.26.99 1.27.1

View File

@ -1,2 +1,2 @@
m4_dnl Version number to show in manuals. Updated by "Shake setversion" m4_dnl Version number to show in manuals. Updated by "Shake setversion"
m4_define({{_version_}}, {{1.26.99}})m4_dnl m4_define({{_version_}}, {{1.27.1}})m4_dnl

View File

@ -9,7 +9,7 @@
Internal/api/developer-ish changes in the hledger-lib (and hledger) packages. Internal/api/developer-ish changes in the hledger-lib (and hledger) packages.
For user-visible changes, see the hledger package changelog. For user-visible changes, see the hledger package changelog.
# 6d4563001 # 1.27 2022-09-01
Breaking changes Breaking changes

View File

@ -89,7 +89,7 @@ data PeriodicReport a b =
} deriving (Show, Functor, Generic, ToJSON) } deriving (Show, Functor, Generic, ToJSON)
instance Bifunctor PeriodicReport where instance Bifunctor PeriodicReport where
bimap f g pr = pr{prRows = map (bimap f g) $ prRows pr, prTotals = fmap g $ prTotals pr} bimap f g pr = pr{prRows = map (bimap f g) $ prRows pr, prTotals = g <$> prTotals pr}
data PeriodicReportRow a b = data PeriodicReportRow a b =
PeriodicReportRow PeriodicReportRow

View File

@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: hledger-lib name: hledger-lib
version: 1.26.99 version: 1.27.1
synopsis: A reusable library providing the core functionality of hledger synopsis: A reusable library providing the core functionality of hledger
description: A reusable library containing hledger's core functionality. description: A reusable library containing hledger's core functionality.
This is used by most hledger* packages so that they support the same This is used by most hledger* packages so that they support the same

View File

@ -1,5 +1,5 @@
name: hledger-lib name: hledger-lib
version: 1.26.99 version: 1.27.1
synopsis: A reusable library providing the core functionality of hledger synopsis: A reusable library providing the core functionality of hledger
description: | description: |
A reusable library containing hledger's core functionality. A reusable library containing hledger's core functionality.

View File

@ -1,2 +1,2 @@
m4_dnl Date to show in man pages. Updated by "Shake manuals" m4_dnl Date to show in man pages. Updated by "Shake manuals"
m4_define({{_monthyear_}}, {{August 2022}})m4_dnl m4_define({{_monthyear_}}, {{September 2022}})m4_dnl

View File

@ -1 +1 @@
1.26.99 1.27.1

View File

@ -1,2 +1,2 @@
m4_dnl Version number to show in manuals. Updated by "Shake setversion" m4_dnl Version number to show in manuals. Updated by "Shake setversion"
m4_define({{_version_}}, {{1.26.99}})m4_dnl m4_define({{_version_}}, {{1.27.1}})m4_dnl

View File

@ -9,7 +9,7 @@
User-visible changes in hledger-ui. User-visible changes in hledger-ui.
See also the hledger changelog. See also the hledger changelog.
# b46cb8a7f # 1.27 2022-09-01
Improvements Improvements

View File

@ -1,5 +1,5 @@
.TH "HLEDGER-UI" "1" "August 2022" "hledger-ui-1.26.99 " "hledger User Manuals" .TH "HLEDGER-UI" "1" "September 2022" "hledger-ui-1.27 " "hledger User Manuals"
@ -7,7 +7,7 @@
.PP .PP
hledger-ui is a terminal interface (TUI) for the hledger accounting hledger-ui is a terminal interface (TUI) for the hledger accounting
tool. tool.
This manual is for hledger-ui 1.26.99. This manual is for hledger-ui 1.27.
.SH SYNOPSIS .SH SYNOPSIS
.PP .PP
\f[C]hledger-ui [OPTIONS] [QUERYARGS]\f[R] \f[C]hledger-ui [OPTIONS] [QUERYARGS]\f[R]

View File

@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: hledger-ui name: hledger-ui
version: 1.26.99 version: 1.27.1
synopsis: Curses-style terminal interface for the hledger accounting system synopsis: Curses-style terminal interface for the hledger accounting system
description: A simple curses-style terminal user interface for the hledger accounting system. description: A simple curses-style terminal user interface for the hledger accounting system.
It can be a more convenient way to browse your accounts than the CLI. It can be a more convenient way to browse your accounts than the CLI.
@ -63,7 +63,7 @@ executable hledger-ui
hs-source-dirs: hs-source-dirs:
./ ./
ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
build-depends: build-depends:
ansi-terminal >=0.9 ansi-terminal >=0.9
, async , async
@ -78,8 +78,8 @@ executable hledger-ui
, extra >=1.6.3 , extra >=1.6.3
, filepath , filepath
, fsnotify >=0.2.1.2 && <0.4 , fsnotify >=0.2.1.2 && <0.4
, hledger >=1.26.99 && <1.27 , hledger >=1.27.1 && <1.28
, hledger-lib >=1.26.99 && <1.27 , hledger-lib >=1.27.1 && <1.28
, megaparsec >=7.0.0 && <9.3 , megaparsec >=7.0.0 && <9.3
, microlens >=0.4 , microlens >=0.4
, microlens-platform >=0.2.3.1 , microlens-platform >=0.2.3.1

View File

@ -12,7 +12,7 @@ hledger-ui(1)
************* *************
hledger-ui is a terminal interface (TUI) for the hledger accounting hledger-ui is a terminal interface (TUI) for the hledger accounting
tool. This manual is for hledger-ui 1.26.99. tool. This manual is for hledger-ui 1.27.
'hledger-ui [OPTIONS] [QUERYARGS]' 'hledger-ui [OPTIONS] [QUERYARGS]'
'hledger ui -- [OPTIONS] [QUERYARGS]' 'hledger ui -- [OPTIONS] [QUERYARGS]'
@ -640,34 +640,34 @@ program is restarted.
 
Tag Table: Tag Table:
Node: Top221 Node: Top221
Node: OPTIONS1657 Node: OPTIONS1654
Ref: #options1755 Ref: #options1752
Node: MOUSE6637 Node: MOUSE6634
Ref: #mouse6732 Ref: #mouse6729
Node: KEYS7014 Node: KEYS7011
Ref: #keys7107 Ref: #keys7104
Node: SCREENS11193 Node: SCREENS11190
Ref: #screens11291 Ref: #screens11288
Node: Accounts screen11381 Node: Accounts screen11378
Ref: #accounts-screen11509 Ref: #accounts-screen11506
Node: Register screen13848 Node: Register screen13845
Ref: #register-screen14003 Ref: #register-screen14000
Node: Transaction screen15987 Node: Transaction screen15984
Ref: #transaction-screen16145 Ref: #transaction-screen16142
Node: Error screen17015 Node: Error screen17012
Ref: #error-screen17137 Ref: #error-screen17134
Node: TIPS17381 Node: TIPS17378
Ref: #tips17480 Ref: #tips17477
Node: Watch mode17532 Node: Watch mode17529
Ref: #watch-mode17649 Ref: #watch-mode17646
Node: Watch mode limitations18399 Node: Watch mode limitations18396
Ref: #watch-mode-limitations18540 Ref: #watch-mode-limitations18537
Node: ENVIRONMENT19676 Node: ENVIRONMENT19673
Ref: #environment19787 Ref: #environment19784
Node: FILES21172 Node: FILES21169
Ref: #files21271 Ref: #files21268
Node: BUGS21484 Node: BUGS21481
Ref: #bugs21561 Ref: #bugs21558
 
End Tag Table End Tag Table

View File

@ -5,7 +5,7 @@ HLEDGER-UI(1) hledger User Manuals HLEDGER-UI(1)
NAME NAME
hledger-ui is a terminal interface (TUI) for the hledger accounting hledger-ui is a terminal interface (TUI) for the hledger accounting
tool. This manual is for hledger-ui 1.26.99. tool. This manual is for hledger-ui 1.27.
SYNOPSIS SYNOPSIS
hledger-ui [OPTIONS] [QUERYARGS] hledger-ui [OPTIONS] [QUERYARGS]
@ -549,4 +549,4 @@ SEE ALSO
hledger-ui-1.26.99 August 2022 HLEDGER-UI(1) hledger-ui-1.27 September 2022 HLEDGER-UI(1)

View File

@ -1,5 +1,5 @@
name : hledger-ui name : hledger-ui
version : 1.26.99 version : 1.27.1
synopsis : Curses-style terminal interface for the hledger accounting system synopsis : Curses-style terminal interface for the hledger accounting system
description : | description : |
A simple curses-style terminal user interface for the hledger accounting system. A simple curses-style terminal user interface for the hledger accounting system.
@ -38,7 +38,7 @@ flags:
manual: false manual: false
default: true default: true
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
ghc-options: ghc-options:
- -Wall - -Wall
@ -50,8 +50,8 @@ ghc-options:
dependencies: dependencies:
- base >=4.14 && <4.17 - base >=4.14 && <4.17
- hledger-lib >=1.26.99 && <1.27 - hledger-lib >=1.27.1 && <1.28
- hledger >=1.26.99 && <1.27 - hledger >=1.27.1 && <1.28
- ansi-terminal >=0.9 - ansi-terminal >=0.9
- async - async
- breakpoint - breakpoint

View File

@ -1,2 +1,2 @@
m4_dnl Date to show in man pages. Updated by "Shake manuals" m4_dnl Date to show in man pages. Updated by "Shake manuals"
m4_define({{_monthyear_}}, {{August 2022}})m4_dnl m4_define({{_monthyear_}}, {{September 2022}})m4_dnl

View File

@ -1 +1 @@
1.26.99 1.27.1

View File

@ -1,2 +1,2 @@
m4_dnl Version number to show in manuals. Updated by "Shake setversion" m4_dnl Version number to show in manuals. Updated by "Shake setversion"
m4_define({{_version_}}, {{1.26.99}})m4_dnl m4_define({{_version_}}, {{1.27.1}})m4_dnl

View File

@ -9,7 +9,7 @@ __ _____| |__
User-visible changes in hledger-web. User-visible changes in hledger-web.
See also the hledger changelog. See also the hledger changelog.
# c97e05e0d # 1.27 2022-09-01
Improvements Improvements
@ -29,6 +29,7 @@ Fixes
- Respect the add form's file selector again. - Respect the add form's file selector again.
(Simon Michael, Kerstin, #1229) (Simon Michael, Kerstin, #1229)
# 1.26.1 2022-07-11 # 1.26.1 2022-07-11
- Uses hledger 1.26.1. - Uses hledger 1.26.1.

View File

@ -154,6 +154,7 @@ instance Yesod App where
|] |]
addScript $ StaticR js_bootstrap_min_js addScript $ StaticR js_bootstrap_min_js
addScript $ StaticR js_bootstrap_datepicker_min_js addScript $ StaticR js_bootstrap_datepicker_min_js
addScript $ StaticR js_locales_bootstrap_datepicker_fi_min_js
addScript $ StaticR js_jquery_url_js addScript $ StaticR js_jquery_url_js
addScript $ StaticR js_jquery_cookie_js addScript $ StaticR js_jquery_cookie_js
addScript $ StaticR js_jquery_hotkeys_js addScript $ StaticR js_jquery_hotkeys_js

View File

@ -31,7 +31,7 @@ postAddR :: Handler ()
postAddR = do postAddR = do
checkServerSideUiEnabled checkServerSideUiEnabled
VD{caps, j, today} <- getViewData VD{caps, j, today} <- getViewData
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability") when (CapAdd `notElem` caps) (permissionDenied "Ei oikeutta lisätä kirjauksia ('add')")
((res, view), enctype) <- runFormPost $ addForm j today ((res, view), enctype) <- runFormPost $ addForm j today
case res of case res of
@ -40,7 +40,7 @@ postAddR = do
liftIO $ do liftIO $ do
ensureJournalFileExists f ensureJournalFileExists f
appendToJournalFileOrStdout f (showTransaction t') appendToJournalFileOrStdout f (showTransaction t')
setMessage "Transaction added." setMessage "Kirjaus lisätty."
redirect JournalR redirect JournalR
FormMissing -> showForm view enctype FormMissing -> showForm view enctype
FormFailure errs -> do FormFailure errs -> do
@ -49,7 +49,7 @@ postAddR = do
where where
showForm view enctype = showForm view enctype =
sendResponse =<< defaultLayout [whamlet| sendResponse =<< defaultLayout [whamlet|
<h2>Add transaction <h2>Uusi kirjaus
<div .row style="margin-top:1em"> <div .row style="margin-top:1em">
<form#addform.form.col-xs-12.col-sm-11 method=post enctype=#{enctype}> <form#addform.form.col-xs-12.col-sm-11 method=post enctype=#{enctype}>
^{view} ^{view}
@ -60,7 +60,7 @@ postAddR = do
putAddR :: Handler RepJson putAddR :: Handler RepJson
putAddR = do putAddR = do
VD{caps, j, opts} <- getViewData VD{caps, j, opts} <- getViewData
when (CapAdd `notElem` caps) (permissionDenied "Missing the 'add' capability") when (CapAdd `notElem` caps) (permissionDenied "Ei oikeutta lisätä kirjauksia ('add')")
(r :: Result Transaction) <- parseCheckJsonBody (r :: Result Transaction) <- parseCheckJsonBody
case r of case r of

View File

@ -32,20 +32,20 @@ postEditR :: FilePath -> Handler ()
postEditR f = do postEditR f = do
checkServerSideUiEnabled checkServerSideUiEnabled
VD {caps, j} <- getViewData VD {caps, j} <- getViewData
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability") when (CapManage `notElem` caps) (permissionDenied "Ei oikeutta muokata kirjanpitoa ('manage')")
(f', txt) <- journalFile404 f j (f', txt) <- journalFile404 f j
((res, view), enctype) <- runFormPost (editForm f' txt) ((res, view), enctype) <- runFormPost (editForm f' txt)
newtxt <- fromFormSuccess (showForm view enctype) res newtxt <- fromFormSuccess (showForm view enctype) res
runExceptT (writeJournalTextIfValidAndChanged f newtxt) >>= \case runExceptT (writeJournalTextIfValidAndChanged f newtxt) >>= \case
Left e -> do Left e -> do
setMessage $ "Failed to load journal: " <> toHtml e setMessage $ "Kirjanpidon lataaminen epäonnistui: " <> toHtml e
showForm view enctype showForm view enctype
Right () -> do Right () -> do
setMessage $ "Saved journal " <> toHtml f <> "\n" setMessage $ "Kirjanpito tallennettu tiedostoon " <> toHtml f <> "\n"
redirect JournalR redirect JournalR
where where
showForm view enctype = showForm view enctype =
sendResponse <=< defaultLayout $ do sendResponse <=< defaultLayout $ do
setTitle "Edit journal" setTitle "Muokkaa kirjanpitoa"
[whamlet|<form method=post enctype=#{enctype}>^{view}|] [whamlet|<form method=post enctype=#{enctype}>^{view}|]

View File

@ -21,16 +21,16 @@ getJournalR :: Handler Html
getJournalR = do getJournalR = do
checkServerSideUiEnabled checkServerSideUiEnabled
VD{caps, j, m, opts, q, qopts, today} <- getViewData VD{caps, j, m, opts, q, qopts, today} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
let title = case inAccount qopts of let title = case inAccount qopts of
Nothing -> "General Journal" Nothing -> "Kaikki kirjaukset"
Just (a, inclsubs) -> "Transactions in " <> a <> if inclsubs then "" else " (excluding subaccounts)" Just (a, inclsubs) -> "Tapahtumat tilillä " <> a <> if inclsubs then "" else " (poislukien alatilit)"
title' = title <> if m /= Any then ", filtered" else "" title' = title <> if m /= Any then ", suodatettu" else ""
acctlink a = (RegisterR, [("q", replaceInacct q $ accountQuery a)]) acctlink a = (RegisterR, [("q", replaceInacct q $ accountQuery a)])
rspec = (reportspec_ $ cliopts_ opts){_rsQuery = m} rspec = (reportspec_ $ cliopts_ opts){_rsQuery = m}
items = reverse $ entriesReport rspec j items = reverse $ entriesReport rspec j
transactionFrag = transactionFragment j transactionFrag = transactionFragment j
defaultLayout $ do defaultLayout $ do
setTitle "journal - hledger-web" setTitle "päiväkirja - hledger-web"
$(widgetFile "journal") $(widgetFile "journal")

View File

@ -39,16 +39,16 @@ getManageR :: Handler Html
getManageR = do getManageR = do
checkServerSideUiEnabled checkServerSideUiEnabled
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability") when (CapManage `notElem` caps) (permissionDenied "Ei oikeutta muokata kirjanpitoa ('manage')")
defaultLayout $ do defaultLayout $ do
setTitle "Manage journal" setTitle "Muokkaa kirjanpitoa"
$(widgetFile "manage") $(widgetFile "manage")
getDownloadR :: FilePath -> Handler TypedContent getDownloadR :: FilePath -> Handler TypedContent
getDownloadR f = do getDownloadR f = do
checkServerSideUiEnabled checkServerSideUiEnabled
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability") when (CapManage `notElem` caps) (permissionDenied "Ei oikeutta muokata kirjanpitoa ('manage')")
(f', txt) <- journalFile404 f j (f', txt) <- journalFile404 f j
addHeader "Content-Disposition" ("attachment; filename=\"" <> T.pack f' <> "\"") addHeader "Content-Disposition" ("attachment; filename=\"" <> T.pack f' <> "\"")
sendResponse ("text/plain" :: ByteString, toContent txt) sendResponse ("text/plain" :: ByteString, toContent txt)
@ -58,49 +58,49 @@ getDownloadR f = do
getVersionR :: Handler TypedContent getVersionR :: Handler TypedContent
getVersionR = do getVersionR = do
VD{caps} <- getViewData VD{caps} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
selectRep $ do selectRep $ do
provideJson $ packageversion provideJson $ packageversion
getAccountnamesR :: Handler TypedContent getAccountnamesR :: Handler TypedContent
getAccountnamesR = do getAccountnamesR = do
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
selectRep $ do selectRep $ do
provideJson $ journalAccountNames j provideJson $ journalAccountNames j
getTransactionsR :: Handler TypedContent getTransactionsR :: Handler TypedContent
getTransactionsR = do getTransactionsR = do
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
selectRep $ do selectRep $ do
provideJson $ jtxns j provideJson $ jtxns j
getPricesR :: Handler TypedContent getPricesR :: Handler TypedContent
getPricesR = do getPricesR = do
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
selectRep $ do selectRep $ do
provideJson $ map priceDirectiveToMarketPrice $ jpricedirectives j provideJson $ map priceDirectiveToMarketPrice $ jpricedirectives j
getCommoditiesR :: Handler TypedContent getCommoditiesR :: Handler TypedContent
getCommoditiesR = do getCommoditiesR = do
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
selectRep $ do selectRep $ do
provideJson $ (M.keys . jinferredcommodities) j provideJson $ (M.keys . jinferredcommodities) j
getAccountsR :: Handler TypedContent getAccountsR :: Handler TypedContent
getAccountsR = do getAccountsR = do
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
selectRep $ do selectRep $ do
provideJson $ laccounts $ ledgerFromJournal Any j provideJson $ laccounts $ ledgerFromJournal Any j
getAccounttransactionsR :: Text -> Handler TypedContent getAccounttransactionsR :: Text -> Handler TypedContent
getAccounttransactionsR a = do getAccounttransactionsR a = do
VD{caps, j} <- getViewData VD{caps, j} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
let let
rspec = defreportspec rspec = defreportspec
thisacctq = Acct $ accountNameToAccountRegex a -- includes subs thisacctq = Acct $ accountNameToAccountRegex a -- includes subs

View File

@ -27,11 +27,11 @@ getRegisterR :: Handler Html
getRegisterR = do getRegisterR = do
checkServerSideUiEnabled checkServerSideUiEnabled
VD{caps, j, m, opts, q, qopts, today} <- getViewData VD{caps, j, m, opts, q, qopts, today} <- getViewData
when (CapView `notElem` caps) (permissionDenied "Missing the 'view' capability") when (CapView `notElem` caps) (permissionDenied "Ei oikeutta katsella kirjanpitoa ('view')")
let (a,inclsubs) = fromMaybe ("all accounts",True) $ inAccount qopts let (a,inclsubs) = fromMaybe ("kaikki tilit",True) $ inAccount qopts
s1 = if inclsubs then "" else " (excluding subaccounts)" s1 = if inclsubs then "" else " (poislukien alitilit)"
s2 = if m /= Any then ", filtered" else "" s2 = if m /= Any then ", suodatettu" else ""
header = a <> s1 <> s2 header = a <> s1 <> s2
let rspec = reportspec_ (cliopts_ opts) let rspec = reportspec_ (cliopts_ opts)
@ -47,12 +47,12 @@ getRegisterR = do
tail $ (", "<$xs) ++ [""] tail $ (", "<$xs) ++ [""]
items = accountTransactionsReport rspec{_rsQuery=m} j acctQuery items = accountTransactionsReport rspec{_rsQuery=m} j acctQuery
balancelabel balancelabel
| isJust (inAccount qopts), balanceaccum_ (_rsReportOpts rspec) == Historical = "Historical Total" | isJust (inAccount qopts), balanceaccum_ (_rsReportOpts rspec) == Historical = "Historiallinen saldo"
| isJust (inAccount qopts) = "Period Total" | isJust (inAccount qopts) = "Kauden saldo"
| otherwise = "Total" | otherwise = "Saldo"
transactionFrag = transactionFragment j transactionFrag = transactionFragment j
defaultLayout $ do defaultLayout $ do
setTitle "register - hledger-web" setTitle "kirjaukset - hledger-web"
$(widgetFile "register") $(widgetFile "register")
-- cf. Hledger.Reports.AccountTransactionsReport.accountTransactionsReportItems -- cf. Hledger.Reports.AccountTransactionsReport.accountTransactionsReportItems

View File

@ -36,7 +36,7 @@ postUploadR :: FilePath -> Handler ()
postUploadR f = do postUploadR f = do
checkServerSideUiEnabled checkServerSideUiEnabled
VD {caps, j} <- getViewData VD {caps, j} <- getViewData
when (CapManage `notElem` caps) (permissionDenied "Missing the 'manage' capability") when (CapManage `notElem` caps) (permissionDenied "Ei oikeutta muokata kirjanpitoa ('manage')")
(f', _) <- journalFile404 f j (f', _) <- journalFile404 f j
((res, view), enctype) <- runFormPost (uploadForm f') ((res, view), enctype) <- runFormPost (uploadForm f')
@ -48,20 +48,20 @@ postUploadR f = do
newtxt <- case TE.decodeUtf8' lbs of newtxt <- case TE.decodeUtf8' lbs of
Left e -> do Left e -> do
setMessage $ setMessage $
"Encoding error: '" <> toHtml (show e) <> "'. " <> "Merkistövirhe: '" <> toHtml (show e) <> "'. " <>
"If your file is not UTF-8 encoded, try the 'edit form', " <> "Jos tiedostosi ei käytä UTF-8 merkistöä, kokeile 'muokkaa'-sivua," <>
"where the transcoding should be handled by the browser." "jolla selaimesi pitäisi huolehtia merkistön muuntamisesta puolestasi."
showForm view enctype showForm view enctype
Right newtxt -> return newtxt Right newtxt -> return newtxt
runExceptT (writeJournalTextIfValidAndChanged f newtxt) >>= \case runExceptT (writeJournalTextIfValidAndChanged f newtxt) >>= \case
Left e -> do Left e -> do
setMessage $ "Failed to load journal: " <> toHtml e setMessage $ "Kirjanpidon lataaminen epäonnistui: " <> toHtml e
showForm view enctype showForm view enctype
Right () -> do Right () -> do
setMessage $ "File " <> toHtml f <> " uploaded successfully" setMessage $ "Tiedoston " <> toHtml f <> " lataaminen onnistui!"
redirect JournalR redirect JournalR
where where
showForm view enctype = showForm view enctype =
sendResponse <=< defaultLayout $ do sendResponse <=< defaultLayout $ do
setTitle "Upload journal" setTitle "Korvaa tiedosto"
[whamlet|<form method=post enctype=#{enctype}>^{view}|] [whamlet|<form method=post enctype=#{enctype}>^{view}|]

View File

@ -38,7 +38,7 @@ addModal addR j today = do
<div .modal-content> <div .modal-content>
<div .modal-header> <div .modal-header>
<button type="button" .close data-dismiss="modal" aria-hidden="true">&times; <button type="button" .close data-dismiss="modal" aria-hidden="true">&times;
<h3 .modal-title #addLabel>Add a transaction <h3 .modal-title #addLabel>Uusi kirjaus
<div .modal-body> <div .modal-body>
<form#addform.form action=@{addR} method=POST enctype=#{addEnctype}> <form#addform.form action=@{addR} method=POST enctype=#{addEnctype}>
^{addView} ^{addView}
@ -49,14 +49,15 @@ addForm j today = identifyForm "add" $ \extra -> do
let -- bindings used in add-form.hamlet let -- bindings used in add-form.hamlet
descriptions = foldMap S.fromList [journalPayeesDeclaredOrUsed j, journalDescriptions j] descriptions = foldMap S.fromList [journalPayeesDeclaredOrUsed j, journalDescriptions j]
files = fst <$> jfiles j files = fst <$> jfiles j
deffile = journalFilePath j
(dateRes, dateView) <- mreq dateField dateSettings Nothing (dateRes, dateView) <- mreq dateField dateSettings Nothing
(descRes, descView) <- mopt textField descSettings Nothing (descRes, descView) <- mopt textField descSettings Nothing
(acctsRes, _) <- mreq listField acctSettings Nothing (acctsRes, _) <- mreq listField acctSettings Nothing
(amtsRes, _) <- mreq listField amtSettings Nothing (amtsRes, _) <- mreq listField amtSettings Nothing
(fileRes, fileView) <- mreq fileField' fileSettings Nothing (fileRes, fileView) <- mopt fileField' fileSettings Nothing
let let
(postingsRes, displayRows) = validatePostings acctsRes amtsRes (postingsRes, displayRows) = validatePostings acctsRes amtsRes
formRes = validateTransaction dateRes descRes postingsRes fileRes formRes = validateTransaction deffile dateRes descRes postingsRes fileRes
return (formRes, $(widgetFile "add-form")) return (formRes, $(widgetFile "add-form"))
where where
-- custom fields -- custom fields
@ -79,29 +80,30 @@ addForm j today = identifyForm "add" $ \extra -> do
| f `elem` fs = Right f | f `elem` fs = Right f
| otherwise = Left $ MsgInputNotFound $ T.pack f | otherwise = Left $ MsgInputNotFound $ T.pack f
-- field settings -- field settings
dateSettings = FieldSettings "date" Nothing Nothing (Just "date") [("class", "form-control input-lg"), ("placeholder", "Date")] dateSettings = FieldSettings "date" Nothing Nothing (Just "date") [("class", "form-control input-lg"), ("placeholder", "Päiväys")]
descSettings = FieldSettings "desc" Nothing Nothing (Just "description") [("class", "form-control input-lg typeahead"), ("placeholder", "Description"), ("size", "40")] descSettings = FieldSettings "desc" Nothing Nothing (Just "description") [("class", "form-control input-lg typeahead"), ("placeholder", "Selite"), ("size", "40")]
acctSettings = FieldSettings "account" Nothing Nothing (Just "account") [] acctSettings = FieldSettings "account" Nothing Nothing (Just "account") []
amtSettings = FieldSettings "amount" Nothing Nothing (Just "amount") [] amtSettings = FieldSettings "amount" Nothing Nothing (Just "amount") []
fileSettings = FieldSettings "file" Nothing Nothing (Just "file") [("class", "form-control input-lg")] fileSettings = FieldSettings "file" Nothing Nothing (Just "file") [("class", "form-control input-lg")]
validateTransaction :: validateTransaction ::
FormResult Day -> FormResult (Maybe Text) -> FormResult [Posting] -> FormResult FilePath FilePath -> FormResult Day -> FormResult (Maybe Text) -> FormResult [Posting] -> FormResult (Maybe FilePath)
-> FormResult (Transaction, FilePath) -> FormResult (Transaction, FilePath)
validateTransaction dateRes descRes postingsRes fileRes = validateTransaction deffile dateRes descRes postingsRes fileRes =
case makeTransaction <$> dateRes <*> descRes <*> postingsRes <*> fileRes of case makeTransaction <$> dateRes <*> descRes <*> postingsRes <*> fileRes of
FormSuccess (txn,f) -> case balanceTransaction defbalancingopts txn of FormSuccess (txn,f) -> case balanceTransaction defbalancingopts txn of
Left e -> FormFailure [T.pack e] Left e -> FormFailure [T.pack e]
Right txn' -> FormSuccess (txn',f) Right txn' -> FormSuccess (txn',f)
x -> x x -> x
where where
makeTransaction date mdesc postings f = makeTransaction date mdesc postings mfile =
(nulltransaction { (nulltransaction {
tdate = date tdate = date
,tdescription = fromMaybe "" mdesc ,tdescription = fromMaybe "" mdesc
,tpostings = postings ,tpostings = postings
,tsourcepos = (initialPos f, initialPos f) ,tsourcepos = (initialPos f, initialPos f)
}, f) }, f)
where f = fromMaybe deffile mfile
-- | Parse a list of postings out of a list of accounts and a corresponding list -- | Parse a list of postings out of a list of accounts and a corresponding list
-- of amounts -- of amounts
@ -188,7 +190,8 @@ toBloodhoundJson ts =
"]" "]"
] ]
where where
b64wrap = ("atob(\""<>) . (<>"\")") . encodeBase64 -- decodeBase64EncodedText is defined in add-form.hamlet
b64wrap = ("decodeBase64EncodedText(\""<>) . (<>"\")") . encodeBase64
zipDefault :: a -> [a] -> [a] -> [(a, a)] zipDefault :: a -> [a] -> [a] -> [(a, a)]
zipDefault def (b:bs) (c:cs) = (b, c):(zipDefault def bs cs) zipDefault def (b:bs) (c:cs) = (b, c):(zipDefault def bs cs)

View File

@ -1,12 +1,12 @@
.TH "HLEDGER-WEB" "1" "August 2022" "hledger-web-1.26.99 " "hledger User Manuals" .TH "HLEDGER-WEB" "1" "September 2022" "hledger-web-1.27 " "hledger User Manuals"
.SH NAME .SH NAME
.PP .PP
hledger-web is a web interface (WUI) for the hledger accounting tool. hledger-web is a web interface (WUI) for the hledger accounting tool.
This manual is for hledger-web 1.26.99. This manual is for hledger-web 1.27.
.SH SYNOPSIS .SH SYNOPSIS
.PP .PP
\f[C]hledger-web [OPTIONS]\f[R] \f[C]hledger-web [OPTIONS]\f[R]

View File

@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: hledger-web name: hledger-web
version: 1.26.99 version: 1.27.1
synopsis: Web-based user interface for the hledger accounting system synopsis: Web-based user interface for the hledger accounting system
description: A simple web-based user interface for the hledger accounting system, description: A simple web-based user interface for the hledger accounting system,
providing a more modern UI than the command-line or terminal interfaces. providing a more modern UI than the command-line or terminal interfaces.
@ -92,6 +92,7 @@ extra-source-files:
static/js/jquery.js static/js/jquery.js
static/js/jquery.min.js static/js/jquery.min.js
static/js/jquery.url.js static/js/jquery.url.js
static/js/locales/bootstrap-datepicker.fi.min.js
static/js/typeahead.bundle.js static/js/typeahead.bundle.js
static/js/typeahead.bundle.min.js static/js/typeahead.bundle.min.js
templates/add-form.hamlet templates/add-form.hamlet
@ -151,7 +152,7 @@ library
hs-source-dirs: hs-source-dirs:
./ ./
ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
build-depends: build-depends:
Decimal >=0.5.1 Decimal >=0.5.1
, aeson >=1 , aeson >=1
@ -172,8 +173,8 @@ library
, extra >=1.6.3 , extra >=1.6.3
, filepath , filepath
, hjsmin , hjsmin
, hledger >=1.26.99 && <1.27 , hledger >=1.27.1 && <1.28
, hledger-lib >=1.26.99 && <1.27 , hledger-lib >=1.27.1 && <1.28
, hspec , hspec
, http-client , http-client
, http-conduit , http-conduit
@ -213,7 +214,7 @@ executable hledger-web
hs-source-dirs: hs-source-dirs:
app app
ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
build-depends: build-depends:
base >=4.14 && <4.17 base >=4.14 && <4.17
, breakpoint , breakpoint
@ -234,7 +235,7 @@ test-suite test
hs-source-dirs: hs-source-dirs:
test test
ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns ghc-options: -Wall -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
build-depends: build-depends:
base >=4.14 && <4.17 base >=4.14 && <4.17
, breakpoint , breakpoint

View File

@ -12,7 +12,7 @@ hledger-web(1)
************** **************
hledger-web is a web interface (WUI) for the hledger accounting tool. hledger-web is a web interface (WUI) for the hledger accounting tool.
This manual is for hledger-web 1.26.99. This manual is for hledger-web 1.27.
'hledger-web [OPTIONS]' 'hledger-web [OPTIONS]'
'hledger web -- [OPTIONS]' 'hledger web -- [OPTIONS]'
@ -632,22 +632,22 @@ awkward.
 
Tag Table: Tag Table:
Node: Top223 Node: Top223
Node: OPTIONS1889 Node: OPTIONS1886
Ref: #options1994 Ref: #options1991
Node: PERMISSIONS9905 Node: PERMISSIONS9902
Ref: #permissions10044 Ref: #permissions10041
Node: EDITING UPLOADING DOWNLOADING11256 Node: EDITING UPLOADING DOWNLOADING11253
Ref: #editing-uploading-downloading11437 Ref: #editing-uploading-downloading11434
Node: RELOADING12271 Node: RELOADING12268
Ref: #reloading12405 Ref: #reloading12402
Node: JSON API12838 Node: JSON API12835
Ref: #json-api12952 Ref: #json-api12949
Node: ENVIRONMENT18442 Node: ENVIRONMENT18439
Ref: #environment18558 Ref: #environment18555
Node: FILES19869 Node: FILES19866
Ref: #files19969 Ref: #files19966
Node: BUGS20182 Node: BUGS20179
Ref: #bugs20260 Ref: #bugs20257
 
End Tag Table End Tag Table

View File

@ -5,7 +5,7 @@ HLEDGER-WEB(1) hledger User Manuals HLEDGER-WEB(1)
NAME NAME
hledger-web is a web interface (WUI) for the hledger accounting tool. hledger-web is a web interface (WUI) for the hledger accounting tool.
This manual is for hledger-web 1.26.99. This manual is for hledger-web 1.27.
SYNOPSIS SYNOPSIS
hledger-web [OPTIONS] hledger-web [OPTIONS]
@ -586,4 +586,4 @@ SEE ALSO
hledger-web-1.26.99 August 2022 HLEDGER-WEB(1) hledger-web-1.27 September 2022 HLEDGER-WEB(1)

View File

@ -1,5 +1,5 @@
name: hledger-web name: hledger-web
version: 1.26.99 version: 1.27.1
synopsis: Web-based user interface for the hledger accounting system synopsis: Web-based user interface for the hledger accounting system
description: | description: |
A simple web-based user interface for the hledger accounting system, A simple web-based user interface for the hledger accounting system,
@ -83,7 +83,7 @@ dependencies:
library: library:
source-dirs: . source-dirs: .
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
exposed-modules: exposed-modules:
- Hledger.Web - Hledger.Web
- Hledger.Web.Application - Hledger.Web.Application
@ -103,8 +103,8 @@ library:
- Hledger.Web.Widget.AddForm - Hledger.Web.Widget.AddForm
- Hledger.Web.Widget.Common - Hledger.Web.Widget.Common
dependencies: dependencies:
- hledger-lib >=1.26.99 && <1.27 - hledger-lib >=1.27.1 && <1.28
- hledger >=1.26.99 && <1.27 - hledger >=1.27.1 && <1.28
- aeson >=1 - aeson >=1
- base64 - base64
- blaze-html - blaze-html
@ -153,7 +153,7 @@ executables:
hledger-web: hledger-web:
source-dirs: app source-dirs: app
main: main.hs main: main.hs
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
dependencies: dependencies:
- hledger-web - hledger-web
when: when:
@ -167,7 +167,7 @@ tests:
source-dirs: test source-dirs: test
main: test.hs main: test.hs
other-modules: [] # prevent double compilation, https://github.com/sol/hpack/issues/188 other-modules: [] # prevent double compilation, https://github.com/sol/hpack/issues/188
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
dependencies: dependencies:
- hledger-lib - hledger-lib
- hledger - hledger

View File

@ -14,6 +14,7 @@ $(document).ready(function() {
autoclose: true, autoclose: true,
format: 'yyyy-mm-dd', format: 'yyyy-mm-dd',
todayHighlight: true, todayHighlight: true,
language: 'fi',
weekStart: 1 // Monday weekStart: 1 // Monday
});; });;
@ -109,11 +110,11 @@ function registerChart($container, series) {
/* https://github.com/krzysu/flot.tooltip */ /* https://github.com/krzysu/flot.tooltip */
tooltip: true, tooltip: true,
tooltipOpts: { tooltipOpts: {
xDateFormat: "%Y/%m/%d", xDateFormat: "%d.%m.%Y",
content: content:
function(label, x, y, flotitem) { function(label, x, y, flotitem) {
var data = flotitem.series.data[flotitem.dataIndex]; var data = flotitem.series.data[flotitem.dataIndex];
return data[3]+" balance on %x after "+data[2]+" posted by transaction:<pre>"+data[4]+"</pre>"; return data[3]+" saldoa %x sen jälkeen, kun siirrettiin "+data[2]+" kirjauksella: <pre>"+data[4]+"</pre>";
}, },
onHover: function(flotitem, $tooltipel) { onHover: function(flotitem, $tooltipel) {
$tooltipel.css('border-color',flotitem.series.color); $tooltipel.css('border-color',flotitem.series.color);
@ -193,8 +194,8 @@ function addformAddPosting() {
$('#addform .account-postings').append( $('#addform .account-group:last').clone().addClass('added-row') ); $('#addform .account-postings').append( $('#addform .account-group:last').clone().addClass('added-row') );
// renumber and clear the new last account and amount fields // renumber and clear the new last account and amount fields
var n = $('#addform .account-group').length; var n = $('#addform .account-group').length;
$('.account-input:last').prop('placeholder', 'Account '+n).val(''); $('.account-input:last').prop('placeholder', 'Tili '+n).val('');
$('.amount-input:last').prop('placeholder','Amount '+n).val(''); // XXX Enable typehead on dynamically created inputs $('.amount-input:last').prop('placeholder','Summa '+n).val(''); // XXX Enable typehead on dynamically created inputs
// and move the keypress handler to the new last amount field // and move the keypress handler to the new last amount field
addformLastAmountBindKey(); addformLastAmountBindKey();
} }

View File

@ -0,0 +1 @@
!function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"],daysShort:["sun","maa","tii","kes","tor","per","lau"],daysMin:["su","ma","ti","ke","to","pe","la"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",clear:"Tyhjennä",weekStart:1,format:"d.m.yyyy"}}(jQuery);

View File

@ -19,6 +19,17 @@
jQuery('input[name=description]').typeahead({ highlight: true }, { source: descriptionsSuggester.ttAdapter() }); jQuery('input[name=description]').typeahead({ highlight: true }, { source: descriptionsSuggester.ttAdapter() });
jQuery('input[name=account]').typeahead({ highlight: true }, { source: accountsSuggester.ttAdapter() }); jQuery('input[name=account]').typeahead({ highlight: true }, { source: accountsSuggester.ttAdapter() });
}); });
const utf8textdecoder = new TextDecoder();
function decodeBase64EncodedText(b64) {
const unb64 = window.atob(b64);
const arr = new Uint8Array(unb64.length);
for (let i = 0; i < arr.length; i++) {
arr[i] = unb64.charCodeAt(i);
}
return utf8textdecoder.decode(arr);
}
^{extra} ^{extra}
<div .row> <div .row>
@ -40,23 +51,23 @@
<div .form-group .row .account-group style="padding-left:1em;"> <div .form-group .row .account-group style="padding-left:1em;">
<div .col-sm-9.col-xs-9 :isJust accE:.has-error> <div .col-sm-9.col-xs-9 :isJust accE:.has-error>
<input .account-input.form-control.input-lg.typeahead type=text <input .account-input.form-control.input-lg.typeahead type=text
name=account placeholder="Account #{n}" value="#{acc}"> name=account placeholder="Tili #{n}" value="#{acc}">
$maybe err <- accE $maybe err <- accE
<span .help-block .error-block>_{err} <span .help-block .error-block>_{err}
<div .col-sm-3.col-xs-3 :isJust amtE:.has-error> <div .col-sm-3.col-xs-3 :isJust amtE:.has-error>
<input .amount-input.form-control.input-lg type=text <input .amount-input.form-control.input-lg type=text
name=amount placeholder="Amount #{n}" value="#{amt}"> name=amount placeholder="Summa #{n}" value="#{amt}">
$maybe err <- amtE $maybe err <- amtE
<span .help-block .error-block>_{err} <span .help-block .error-block>_{err}
<div .row> <div .row>
<div .col-sm-9.col-xs-9> <div .col-sm-9.col-xs-9>
$if length files > 1 $if length files > 1
Add to: Kirjaa tiedostoon:
&nbsp; &nbsp;
<div style="display:inline-block; width:auto;" .form-group :isJust (fvErrors fileView):.has-error> <div style="display:inline-block; width:auto;" .form-group :isJust (fvErrors fileView):.has-error>
^{fvInput fileView} ^{fvInput fileView}
$maybe err <- fvErrors fileView $maybe err <- fvErrors fileView
<span .help-block .error-block>#{err} <span .help-block .error-block>#{err}
<div .col-sm-3.col-xs-3 style="text-align:right;"> <div .col-sm-3.col-xs-3 style="text-align:right;">
<button type=submit .btn .btn-default .btn-lg name=submit style="font-weight:bold;">Save <button type=submit .btn .btn-default .btn-lg name=submit style="font-weight:bold;">Tallenna

View File

@ -1,8 +1,8 @@
<tr :here == journalR:.inacct> <tr :here == journalR:.inacct>
<td .top .acct> <td .top .acct>
<a href=@{journalR} :here == journalR:.inacct <a href=@{journalR} :here == journalR:.inacct
title="Show general journal entries, most recent first"> title="Näytä päiväkirjan kirjaukset uusimmasta vanhimpaan">
Journal Kirjanpito
<td .top> <td .top>
$forall (acct, adisplay, aindent, abal) <- items $forall (acct, adisplay, aindent, abal) <- items
<tr <tr
@ -12,11 +12,11 @@ $forall (acct, adisplay, aindent, abal) <- items
<div .ff-wrapper> <div .ff-wrapper>
\#{indent aindent} \#{indent aindent}
<a.acct-name href="@?{(registerR, [("q", replaceInacct q $ accountQuery acct)])}" <a.acct-name href="@?{(registerR, [("q", replaceInacct q $ accountQuery acct)])}"
title="Show transactions affecting this account and subaccounts"> title="Näytä tähän tiliin ja sen alitileihin vaikuttavat kirjaukset">
#{adisplay} #{adisplay}
$if hasSubAccounts acct $if hasSubAccounts acct
<a href="@?{(registerR, [("q", replaceInacct q $ accountOnlyQuery acct)])}" .only.hidden-sm.hidden-xs <a href="@?{(registerR, [("q", replaceInacct q $ accountOnlyQuery acct)])}" .only.hidden-sm.hidden-xs
title="Show transactions affecting this account but not subaccounts">only title="Näytä vain juuri tähän tiliin vaikuttavat kirjaukset">only
<td> <td>
^{mixedAmountAsHtml abal} ^{mixedAmountAsHtml abal}
<tr .total> <tr .total>

View File

@ -17,19 +17,19 @@ $if elem CapView caps
<div #message .alert.alert-info>#{m} <div #message .alert.alert-info>#{m}
$if elem CapView caps $if elem CapView caps
<form#searchform.input-group method=GET> <form#searchform.input-group method=GET>
<input .form-control name=q value=#{q} placeholder="Search" <input .form-control name=q value=#{q} placeholder="Hae"
title="Enter hledger search patterns to filter the data below"> title="Syötä hakuehtoja rajataksesi alla olevaa dataa">
<div .input-group-btn> <div .input-group-btn>
$if not (T.null q) $if not (T.null q)
<a href=@{here} .btn .btn-default title="Clear search terms"> <a href=@{here} .btn .btn-default title="Tyhjennä hakuehdot">
<span .glyphicon .glyphicon-remove-circle> <span .glyphicon .glyphicon-remove-circle>
<button .btn .btn-default type=submit title="Apply search terms"> <button .btn .btn-default type=submit title="Hae">
<span .glyphicon .glyphicon-search> <span .glyphicon .glyphicon-search>
$if elem CapManage caps $if elem CapManage caps
<a href="@{ManageR}" .btn.btn-default title="Manage journal files"> <a href="@{ManageR}" .btn.btn-default title="Hallinnoi kirjanpidon tiedostoja">
<span .glyphicon .glyphicon-wrench> <span .glyphicon .glyphicon-wrench>
<button .btn .btn-default type=button data-toggle="modal" data-target="#helpmodal" <button .btn .btn-default type=button data-toggle="modal" data-target="#helpmodal"
title="Show search and general help"> title="Näytä käyttöohjeita">
<span .glyphicon .glyphicon-question-sign> <span .glyphicon .glyphicon-question-sign>
^{widget} ^{widget}
@ -38,43 +38,43 @@ $if elem CapView caps
<div .modal-content> <div .modal-content>
<div .modal-header> <div .modal-header>
<button type="button" .close data-dismiss="modal" aria-hidden="true">&times; <button type="button" .close data-dismiss="modal" aria-hidden="true">&times;
<h3 .modal-title #helpLabel>Help <h3 .modal-title #helpLabel>Ohjeet
<div .modal-body> <div .modal-body>
<div .row> <div .row>
<div .col-xs-6> <div .col-xs-6>
<p> <p>
<b>Keyboard shortcuts <b>Pikanäppäimet
<ul> <ul>
<li> <code>h</code> or maybe <code>?</code> - view this help (escape or click to exit) <li> <code>h</code> tai (selaimesta riippuen) myös <code>?</code> - näytä nämä ohjeet (paina <code>esc</code> tai klikkaa ruksia poistuaksesi)
<li> <code>j</code> - go to the Journal view (home) <li> <code>j</code> - siirry päiväkirjanäkymään (etusivulle)
<li> <code>a</code> - add a transaction (escape to cancel) <li> <code>a</code> - lisää uusi kirjaus (paina <code>esc</code> peruaksesi)
<li> <code>s</code> - toggle sidebar <li> <code>s</code> - vaihda sivupalkki näkyviin/piilotetuksi
<li> <code>f</code> - focus search form ("find") <li> <code>f</code> - kohdista hakukenttään
<li> <code>e</code> - hide empty accounts in sidebar <li> <code>e</code> - piilota nollasaldoiset tilit sivupalkista
<p> <p>
<b>General <b>Yleistä
<ul> <ul>
<li> The Journal view shows general journal entries, representing zero-sum movements of money (or other commodity) between hierarchical accounts <li> Pääkirja näytää kirjauksia, jotka esittävät rahan (tai muun hyödykkeen) täydellisiä siirtoja tilien välillä. Siirron täydellisyydellä tarkoitetaan sitä, ettei siitä ole jätetty mitään osaa kirjaamatta, jolloin hyödykettä ei katoa eikä synny tyhjästä.
<li> The sidebar shows the resulting accounts and their final balances <li> Sivupalkki näyttää käytetyt tilit ja niiden loppusaldot
<li> Parent account balances include subaccount balances <li> Ylätilien saldot sisältävät niiden alatilien saldot
<li> Multiple currencies in balances are displayed one above the other <li> Eri valuutat esitetään saldoissa päällekkäin
<li> Click account name links to see transactions affecting that account, with running balance <li> Klikkaamalla tilin nimeä näet siihen vaikuttavat kirjaukset ja saldon joka siirron jälkeen
<li> Click date links to see journal entries on that date <li> Klikkaamalla päiväystä näet silloin kirjatut tapahtumat
<div .col-xs-6> <div .col-xs-6>
<p> <p>
<b>Search <b>Haku
<ul> <ul>
<li> <code>acct:REGEXP</code> - filter on to/from account <li> <code>acct:REGEXP</code> - suodata tilin nimellä
<li> <code>desc:REGEXP</code> - filter on description <li> <code>desc:REGEXP</code> - suodata selitteellä
<li> <code>date:PERIODEXP</code>, <code>date2:PERIODEXP</code> - filter on date or secondary date <li> <code>date:AIKAVÄLI</code>, <code>date2:AIKAVÄLI</code> - suodata päiväyksen tai toissijaisen päiväkysen perusteella.
<li> <code>code:REGEXP</code> - filter on transaction's code (eg check number) <li> <code>code:REGEXP</code> - suodata kirjauksen numerolla (esim. tilisiirron viitenumero)
<li> <code>status:*</code>, <code>status:!</code>, <code>status:</code> - filter on transaction's cleared status (cleared, pending, uncleared) <li> <code>status:*</code>, <code>status:!</code>, <code>status:</code> - suodata kirjauksen tilan perusteella (valmis, kesken, tarkistamaton)
<!-- <li> <code>empty:BOOL</code> - filter on whether amount is zero --> <!-- <li> <code>empty:BOOL</code> - suodata sen perusteella, onko tilin saldo nolla -->
<li> <code>amt:N</code>, <code>amt:&lt;N</code>, <code>amt:&gt;N</code> - filter on the unsigned amount magnitude. Or with a sign before N, filter on the signed value. (Single-commodity amounts only.) <li> <code>amt:N</code>, <code>amt:&lt;N</code>, <code>amt:&gt;N</code> - suodata summan (itseisarvon) suuruuden perusteella. Etumerkin + tai &minus; lisääminen luvun <code>N</code> eteen rajoittaa suodatuksen vain sen merkkisiin summiin. (ei yhdistä eri valuuttojen määriä)
<li> <code>cur:REGEXP</code> - filter on the currency/commodity symbol (must match all of it). Dollar sign must be written as <code>\$</code> <li> <code>cur:REGEXP</code> - suodata valuutan/hyödykkeen tunnuksella. (koko tunnuksen täytyy täsmätä)
<li> <code>tag:NAME</code>, <code>tag:NAME=REGEX</code> - filter on tag name, or tag name and value <li> <code>tag:NIMI</code>, <code>tag:NIMI=REGEX</code> - suodata tunnisteen nimellä tai nimellä ja arvolla
<!-- <li> <code>depth:N</code> - filter out accounts below this depth --> <!-- <li> <code>depth:N</code> - rajoita niihin tileihin, joilla on alle <code>N</code> ylätiliä -->
<li> <code>real:BOOL</code> - filter on postings' real/virtual-ness <li> <code>real:BOOL</code> - suodata siirtojen todellisuuden/näennäisyyden perusteella. Näennäissiirtojen summa ei välttämättä ole nolla, eli ne voivat hävittää kirjanpidosta rahaa tai tuoda sitä sinne tyhjästä.
<li> Enclose search patterns containing spaces in single or double quotes <li> Hakuehdot erotellaan välilyönneillä. Välilyönnin voi sisällyttää hakuehtoon ympäröimällä ehdon yksin- tai kaksinkertaisilla suorilla lainausmerkeillä (<code>"</code> tai <code>'</code>)
<li> Prepend <code>not:</code> to negate a search term <li> Lisää ehdon alkuun <code>not:</code> valitaksesi ne tapahtumat, jotka eivät toteuta ehtoa
<li> Description, account, status query terms are OR'ed, others are AND'ed. <li> Selitteen, tilin nimen ja kirjauksen tilan hakuehdoista riittää toteuttaa yksi, muista ehdoista tapahtuman pitää toteuttaa kaikki tullakseen valituksi.

View File

@ -1,9 +1,9 @@
#{extra} #{extra}
<h2> <h2>
Edit file # Muokkaa tiedostoa #
<i>#{f} <i>#{f}
<div.alert.alert-danger> <div.alert.alert-danger>
Are you sure? This will overwrite your journal! Oletko varma? Tämä korvaa vanhan tiedoston täysin!
<table.table.table-condensed> <table.table.table-condensed>
<tr> <tr>
<td colspan=2 style="border:0"> <td colspan=2 style="border:0">
@ -11,7 +11,7 @@
<tr> <tr>
<td style="border:0"> <td style="border:0">
<span.help> <span.help>
^{helplink "file-format" "File format help"} ^{helplink "file-format" "Apua tiedostomudon kanssa (englanniksi)"}
<td .text-right style="border:0"> <td .text-right style="border:0">
<a.btn.btn-default href="@{ManageR}">Go back <a.btn.btn-default href="@{ManageR}">Peruuta
<input.btn.btn-default type=submit value="Save"> <input.btn.btn-default type=submit value="Tallenna">

View File

@ -3,16 +3,16 @@
$if elem CapAdd caps $if elem CapAdd caps
<a #addformlink href="#" role="button" style="cursor:pointer; margin-top:1em;" <a #addformlink href="#" role="button" style="cursor:pointer; margin-top:1em;"
data-toggle="modal" data-target="#addmodal" title="Add a new transaction to the journal"> data-toggle="modal" data-target="#addmodal" title="Lisää uusi tapahtuma kirjanpitoon.">
Add a transaction Kirjaa tapahtuma
<div .table-responsive> <div .table-responsive>
<table .transactionsreport .table .table-condensed> <table .transactionsreport .table .table-condensed>
<thead> <thead>
<th .date style="text-align:left;">Date <th .date style="text-align:left;">Päiväys
<th .description style="text-align:left;">Description <th .description style="text-align:left;">Selite
<th .account style="text-align:left;">Account <th .account style="text-align:left;">Tili
<th .amount style="text-align:right;">Amount <th .amount style="text-align:right;">Summa
$forall torig <- items $forall torig <- items
<tr .title ##{transactionFrag torig} title="#{showTransaction torig}"> <tr .title ##{transactionFrag torig} title="#{showTransaction torig}">

View File

@ -1,12 +1,12 @@
<h2> <h2>
Your journal's files Kirjanpitosi tiedostot
<div.row> <div.row>
<div .col-md-6.col-sm-8.col-xs-12> <div .col-md-6.col-sm-8.col-xs-12>
<table .table.table-condensed> <table .table.table-condensed>
<thead> <thead>
<th> <th>
File Tiedosto
<th> <th>
<tbody> <tbody>
$forall (path, _) <- jfiles j $forall (path, _) <- jfiles j
@ -15,8 +15,8 @@
#{path} #{path}
<td style="text-align:right"> <td style="text-align:right">
<a.btn.btn-default href=@{EditR path}> <a.btn.btn-default href=@{EditR path}>
Edit Muokkaa
<a.btn.btn-default href=@{UploadR path}> <a.btn.btn-default href=@{UploadR path}>
Upload Korvaa uudella
<a.btn.btn-default href=@{DownloadR path}> <a.btn.btn-default href=@{DownloadR path}>
Download Imuroi

View File

@ -9,11 +9,11 @@
<thead> <thead>
<tr> <tr>
<th style="text-align:left;"> <th style="text-align:left;">
Date Päiväys
<span .glyphicon.glyphicon-chevron-up> <span .glyphicon.glyphicon-chevron-up>
<th style="text-align:left;">Description <th style="text-align:left;">Kuvaus
<th style="text-align:left;">To/From Account(s) <th style="text-align:left;">Tileille/Tileiltä
<th style="text-align:right; white-space:normal;">Amount Out/In <th style="text-align:right; white-space:normal;">Siirretty summa
<th style="text-align:right; white-space:normal;"> <th style="text-align:right; white-space:normal;">
#{balancelabel} #{balancelabel}

View File

@ -1,14 +1,14 @@
<h2> <h2>
Upload to file # Korvaa tiedosto #
<i>#{f} <i>#{f}
<div.alert.alert-danger> <div.alert.alert-danger>
Are you sure? This will overwrite your journal! Oletko varma? Tämä korvaa vanhan tiedoston täysin!
<div.form-group> <div.form-group>
<label .btn.btn-primary for="file"> <label .btn.btn-primary for="file">
<input type=file id=file name=file style="display:none" <input type=file id=file name=file style="display:none"
onchange="\$('#file-info').html(this.files[0].name)" /> onchange="\$('#file-info').html(this.files[0].name)" />
Select file Valitse korvattava tiedosto
<span .label.label-info id="file-info"> <span .label.label-info id="file-info">
<div.form-group> <div.form-group>
<input .btn.btn-default type=submit value="Upload"> <input .btn.btn-default type=submit value="Korvaa">
#{extra} #{extra}

View File

@ -0,0 +1,8 @@
* hledger-web extra tests
Additional, manual tests for hledger-web.
These should be moved to the automated test suite when possible
(Hledger/Web/Test.hs, `stack test hledger-web`).
** hledger-web -f/dev/null, a, submit a transaction: should succeed
Adding to a single file, with no file field showing in the add form, should work. (#1932)

View File

@ -1,2 +1,2 @@
m4_dnl Date to show in man pages. Updated by "Shake manuals" m4_dnl Date to show in man pages. Updated by "Shake manuals"
m4_define({{_monthyear_}}, {{August 2022}})m4_dnl m4_define({{_monthyear_}}, {{September 2022}})m4_dnl

View File

@ -1 +1 @@
1.26.99 1.27.1

View File

@ -1,2 +1,2 @@
m4_dnl Version number to show in manuals. Updated by "Shake setversion" m4_dnl Version number to show in manuals. Updated by "Shake setversion"
m4_define({{_version_}}, {{1.26.99}})m4_dnl m4_define({{_version_}}, {{1.27.1}})m4_dnl

View File

@ -9,7 +9,7 @@
User-visible changes in the hledger command line tool and library. User-visible changes in the hledger command line tool and library.
# b46cb8a7f # 1.27 2022-09-01
Features Features
@ -71,11 +71,7 @@ Fixes
- bal: budget goals were ignoring rule-specified start date - bal: budget goals were ignoring rule-specified start date
- bal: Allow cumulative gain and valuechange reports (Stephen Morgan) - cf/bs/is: Fixed non-display of child accounts when there is an
Previously, --cumulative with --gain or --valuechange would produce an
empty report. This fixes this issue to produce a reasonable report.
- cs/bs/is: Fixed non-display of child accounts when there is an
intervening account of another type. intervening account of another type.
(#1921) (Stephen Morgan) (#1921) (Stephen Morgan)

View File

@ -573,14 +573,20 @@ multiBalanceReportHtmlRows ropts mbr =
-- | Render one MultiBalanceReport heading row as a HTML table row. -- | Render one MultiBalanceReport heading row as a HTML table row.
multiBalanceReportHtmlHeadRow :: ReportOpts -> [T.Text] -> Html () multiBalanceReportHtmlHeadRow :: ReportOpts -> [T.Text] -> Html ()
multiBalanceReportHtmlHeadRow _ [] = mempty -- shouldn't happen multiBalanceReportHtmlHeadRow _ [] = mempty -- shouldn't happen
multiBalanceReportHtmlHeadRow ropts (acct:rest) = multiBalanceReportHtmlHeadRow ropts (acct:cells) =
let let
defstyle = style_ "" defstyle = style_ ""
(amts,tot,avg) (amts,tot,avg)
| row_total_ ropts && average_ ropts = (init $ init rest, [last $ init rest], [last rest]) | row_total_ ropts && average_ ropts = (ini2, sndlst2, lst2)
| row_total_ ropts = (init rest, [last rest], []) | row_total_ ropts = (ini1, lst1, [])
| average_ ropts = (init rest, [], [last rest]) | average_ ropts = (ini1, [], lst1)
| otherwise = (rest, [], []) | otherwise = (cells, [], [])
where
n = length cells
(ini1,lst1) = splitAt (n-1) cells
(ini2, rest) = splitAt (n-2) cells
(sndlst2,lst2) = splitAt 1 rest
in in
tr_ $ mconcat $ tr_ $ mconcat $
td_ [class_ "account"] (toHtml acct) td_ [class_ "account"] (toHtml acct)
@ -591,14 +597,19 @@ multiBalanceReportHtmlHeadRow ropts (acct:rest) =
-- | Render one MultiBalanceReport data row as a HTML table row. -- | Render one MultiBalanceReport data row as a HTML table row.
multiBalanceReportHtmlBodyRow :: ReportOpts -> [T.Text] -> Html () multiBalanceReportHtmlBodyRow :: ReportOpts -> [T.Text] -> Html ()
multiBalanceReportHtmlBodyRow _ [] = mempty -- shouldn't happen multiBalanceReportHtmlBodyRow _ [] = mempty -- shouldn't happen
multiBalanceReportHtmlBodyRow ropts (label:rest) = multiBalanceReportHtmlBodyRow ropts (label:cells) =
let let
defstyle = style_ "text-align:right" defstyle = style_ "text-align:right"
(amts,tot,avg) (amts,tot,avg)
| row_total_ ropts && average_ ropts = (init $ init rest, [last $ init rest], [last rest]) | row_total_ ropts && average_ ropts = (ini2, sndlst2, lst2)
| row_total_ ropts = (init rest, [last rest], []) | row_total_ ropts = (ini1, lst1, [])
| average_ ropts = (init rest, [], [last rest]) | average_ ropts = (ini1, [], lst1)
| otherwise = (rest, [], []) | otherwise = (cells, [], [])
where
n = length cells
(ini1,lst1) = splitAt (n-1) cells
(ini2, rest) = splitAt (n-2) cells
(sndlst2,lst2) = splitAt 1 rest
in in
tr_ $ mconcat $ tr_ $ mconcat $
td_ [class_ "account", style_ "text-align:left"] (toHtml label) td_ [class_ "account", style_ "text-align:left"] (toHtml label)
@ -615,14 +626,19 @@ multiBalanceReportHtmlFootRow _ropts [] = mempty
-- : repeat nullmixedamt zeros -- : repeat nullmixedamt zeros
-- ++ (if row_total_ ropts then [nullmixedamt] else []) -- ++ (if row_total_ ropts then [nullmixedamt] else [])
-- ++ (if average_ ropts then [nullmixedamt] else []) -- ++ (if average_ ropts then [nullmixedamt] else [])
multiBalanceReportHtmlFootRow ropts (acct:rest) = multiBalanceReportHtmlFootRow ropts (acct:cells) =
let let
defstyle = style_ "text-align:right" defstyle = style_ "text-align:right"
(amts,tot,avg) (amts,tot,avg)
| row_total_ ropts && average_ ropts = (init $ init rest, [last $ init rest], [last rest]) | row_total_ ropts && average_ ropts = (ini2, sndlst2, lst2)
| row_total_ ropts = (init rest, [last rest], []) | row_total_ ropts = (ini1, lst1, [])
| average_ ropts = (init rest, [], [last rest]) | average_ ropts = (ini1, [], lst1)
| otherwise = (rest, [], []) | otherwise = (cells, [], [])
where
n = length cells
(ini1,lst1) = splitAt (n-1) cells
(ini2, rest) = splitAt (n-2) cells
(sndlst2,lst2) = splitAt 1 rest
in in
tr_ $ mconcat $ tr_ $ mconcat $
th_ [style_ "text-align:left"] (toHtml acct) th_ [style_ "text-align:left"] (toHtml acct)

View File

@ -1,6 +1,6 @@
.\"t .\"t
.TH "HLEDGER" "1" "August 2022" "hledger-1.26.99 " "hledger User Manuals" .TH "HLEDGER" "1" "September 2022" "hledger-1.27 " "hledger User Manuals"
@ -9,7 +9,7 @@
This is the command-line interface (CLI) for the hledger accounting This is the command-line interface (CLI) for the hledger accounting
tool. tool.
Here we also describe hledger\[aq]s concepts and file formats. Here we also describe hledger\[aq]s concepts and file formats.
This manual is for hledger 1.26.99. This manual is for hledger 1.27.
.SH SYNOPSIS .SH SYNOPSIS
.PP .PP
\f[C]hledger\f[R] \f[C]hledger\f[R]
@ -1564,38 +1564,257 @@ not the old one, and \f[C]amt:\f[R] matches the new quantity, and not
the old one. the old one.
Note: this changed in hledger 1.22, previously it was the reverse, see Note: this changed in hledger 1.22, previously it was the reverse, see
the discussion at #1625. the discussion at #1625.
.SH CONVERSION & COST .SH COST
.PP .PP
This section is about converting between commodities. This section is about recording the cost of things, in transactions
Some definitions: where one commodity is exchanged for another.
Eg an exchange of currency, or a stock purchase or sale.
First, a quick glossary:
.IP \[bu] 2 .IP \[bu] 2
A \[dq]commodity conversion\[dq] is an exchange of one currency or Conversion - an exchange of one currency or commodity for another.
commodity for another.
Eg a foreign currency exchange, or a purchase or sale of stock or Eg a foreign currency exchange, or a purchase or sale of stock or
cryptocurrency. cryptocurrency.
.IP \[bu] 2 .IP \[bu] 2
A \[dq]conversion transaction\[dq] is a transaction involving one or Conversion transaction - a transaction involving one or more
more such conversions. conversions.
.IP \[bu] 2 .IP \[bu] 2
\[dq]Conversion rate\[dq] is the exchange rate in a conversion - the Conversion rate - the cost per unit of one commodity in the other, ie
cost per unit of one commodity in the other. the exchange rate.
.IP \[bu] 2 .IP \[bu] 2
\[dq]Cost\[dq] is how much of one commodity was paid to acquire the Cost - how much of one commodity was paid to acquire the other.
other (when buying), or how much was received in exchange for the other And more generally, in hledger docs: the amount exchanged in the
(when selling). \[dq]secondary\[dq] commodity (usually your base currency), whether in a
We call both of these \[dq]cost\[dq] for convenience (after all, it is purchase or a sale, and whether expressed per unit or in total.
cost for one party or the other). Or, the \[at]/\[at]\[at] notation used to represent this.
.SS Recording conversions .IP \[bu] 2
Transaction price - another name for the cost expressed with
hledger\[aq]s cost notation.
.SS -B: Convert to cost
.PP .PP
As a concrete example, let\[aq]s assume 100 EUR was converted to 120 As discussed a little further on in Transaction prices, when recording a
USD. transaction you can also record the amount\[aq]s cost in another
There are several ways to record this in the journal, each with pros and commodity, by adding \f[C]\[at] UNITPRICE\f[R] or
cons which will be explained in more detail below. \f[C]\[at]\[at] TOTALPRICE\f[R].
(Also, these examples use journal format which is properly explained
much further below; sorry about that, you may want to read some of that
first.)
.SS Implicit conversion
.PP .PP
Then you can see a report with amounts converted to cost, by adding the
\f[C]-B/--cost\f[R] flag.
(Mnemonic: \[dq]B\[dq] from \[dq]cost Basis\[dq], as in Ledger).
Eg:
.IP
.nf
\f[C]
2022-01-01
assets:dollars $-135 ; 135 dollars is exchanged for..
assets:euros \[Eu]100 \[at] $1.35 ; one hundred euros purchased at $1.35 each
\f[R]
.fi
.IP
.nf
\f[C]
$ hledger bal -N
$-135 assets:dollars
\[Eu]100 assets:euros
$ hledger bal -N -B
$-135 assets:dollars
$135 assets:euros # <- the euros\[aq] cost
\f[R]
.fi
.PP
Notes:
.PP
-B is sensitive to the order of postings when a transaction price is
inferred: the inferred price will be in the commodity of the last
amount.
So if example 3\[aq]s postings are reversed, while the transaction is
equivalent, -B shows something different:
.IP
.nf
\f[C]
2022-01-01
assets:dollars $-135 ; 135 dollars sold
assets:euros \[Eu]100 ; for 100 euros
\f[R]
.fi
.IP
.nf
\f[C]
$ hledger bal -N -B
\[Eu]-100 assets:dollars # <- the dollars\[aq] selling price
\[Eu]100 assets:euros
\f[R]
.fi
.PP
The \[at]/\[at]\[at] cost notation is convenient, but has some
drawbacks: it does not truly balance the transaction, so it disrupts the
accounting equation and tends to causes a non-zero total in balance
reports.
.SS Equity conversion postings
.PP
By contrast, conventional double entry bookkeeping (DEB) uses a
different notation: an extra pair of equity postings to balance
conversion transactions.
In this style, the above entry might be written:
.IP
.nf
\f[C]
2022-01-01 one hundred euros purchased at $1.35 each
assets:dollars $-135
equity:conversion $135
equity:conversion \[Eu]-100
assets:euros \[Eu]100
\f[R]
.fi
.PP
This style is more correct, but it\[aq]s also more verbose and makes
cost reporting more difficult for PTA tools.
.PP
Happily, current hledger can read either notation, or convert one to the
other when needed, so you can use the one you prefer.
.SS Inferring equity postings from cost
.PP
With \f[C]--infer-equity\f[R], hledger detects transactions written with
PTA cost notation and adds equity conversion postings to them (and
temporarily permits the coexistence of equity conversion postings and
cost notation, which normally would cause an unbalanced transaction
error).
Eg:
.IP
.nf
\f[C]
2022-01-01
assets:dollars -$135
assets:euros \[Eu]100 \[at] $1.35
\f[R]
.fi
.IP
.nf
\f[C]
$ hledger print --infer-equity
2022-01-01
assets:dollars $-135
assets:euros \[Eu]100 \[at] $1.35
equity:conversion:$-\[Eu]:\[Eu] \[Eu]-100 ; generated-posting:
equity:conversion:$-\[Eu]:$ $135.00 ; generated-posting:
\f[R]
.fi
.PP
The conversion account names can be changed with the conversion account
type declaration.
.PP
--infer-equity is useful when when transactions have been recorded using
PTA cost notation, to help preserve the accounting equation and balance
reports\[aq] zero total, or to produce more conventional journal entries
for sharing with non-PTA-users.
.PP
\f[I]Experimental\f[R]
.SS Inferring cost from equity postings
.PP
The reverse operation is possible using \f[C]--infer-costs\f[R], which
detects transactions written with equity conversion postings and adds
PTA cost notation to them (and temporarily permits the coexistence of
equity conversion postings and cost notation).
Eg:
.IP
.nf
\f[C]
2022-01-01
assets:dollars $-135
equity:conversion $135
equity:conversion \[Eu]-100
assets:euros \[Eu]100
\f[R]
.fi
.IP
.nf
\f[C]
$ hledger print --infer-costs
2022-01-01
assets:dollars $-135 \[at]\[at] \[Eu]100
equity:conversion $135
equity:conversion \[Eu]-100
assets:euros \[Eu]100
\f[R]
.fi
.PP
--infer-costs is useful when combined with -B/--cost, allowing cost
reporting even when transactions have been recorded using equity
postings:
.IP
.nf
\f[C]
$ hledger print --infer-costs -B
2009-01-01
assets:dollars \[Eu]-100
assets:euros \[Eu]100
\f[R]
.fi
.PP
Notes:
.PP
Postings will be recognised as equity conversion postings if they are 1.
to account(s) declared with type \f[C]V\f[R] (\f[C]Conversion\f[R]; or
if no such accounts are declared, accounts named
\f[C]equity:conversion\f[R], \f[C]equity:trade\f[R],
\f[C]equity:trading\f[R], or subaccounts of these) 2.
adjacent 3.
and exactly matching the amounts of two non-conversion postings.
.PP
The total cost is appended to the first matching posting in the
transaction.
If you need to assign it to a different posting, or if you have several
different sets of conversion postings in one transaction, you may need
to write the costs explicitly yourself.
Eg:
.IP
.nf
\f[C]
2022-01-01
assets:dollars $-135
equity:conversion \[Eu]-100
equity:conversion $135
assets:euros \[Eu]100 \[at]\[at] $135
\f[R]
.fi
.PP
or:
.IP
.nf
\f[C]
2022-01-01
assets:dollars $-235
assets:euros \[Eu]100 \[at] $1.35 ; 100 euros bought for $1.35 each
equity:conversion \[Eu]-100
equity:conversion $135
assets:pounds \[Po]80 \[at]\[at] $100 ; 80 pounds bought for $100 total
equity:conversion \[Po]-80
equity:conversion $100
\f[R]
.fi
.PP
--infer-equity and --infer-costs can be used together, eg if you have a
mixture of both notations.
.PP
\f[I]Experimental\f[R]
.SS When to infer cost/equity
.PP
Inferring equity postings or costs is still fairly new, so not enabled
by default.
We\[aq]re not sure yet if that should change.
Here are two suggestions to try, experience reports welcome:
.IP "1." 3
When you use -B, always use --infer-costs as well.
Eg: \f[C]hledger bal -B --infer-costs\f[R]
.IP "2." 3
Always run hledger with both flags enabled.
Eg: \f[C]alias hl=\[dq]hledger --infer-equity --infer-costs\[dq]\f[R]
.SS How to record conversions
.PP
Essentially there are four ways to record a conversion transaction in
hledger.
Here are all of them, with pros and cons.
.SS Conversion with implicit cost
.PP
Let\[aq]s assume 100 EUR is converted to 120 USD.
You can just record the outflow (100 EUR) and inflow (120 USD) in the You can just record the outflow (100 EUR) and inflow (120 USD) in the
appropriate asset account: appropriate asset account:
.IP .IP
@ -1613,25 +1832,24 @@ You can see the inferred rate by using \f[C]hledger print -x\f[R].
.PP .PP
Pro: Pro:
.IP \[bu] 2 .IP \[bu] 2
Easy, concise Concise, easy
.IP \[bu] 2
hledger can do cost reporting
.PP .PP
Con: Con:
.IP \[bu] 2 .IP \[bu] 2
Less error checking - typos in amounts or commodity symbols may not be Less error checking - typos in amounts or commodity symbols may not be
detected detected
.IP \[bu] 2 .IP \[bu] 2
conversion rate is not clear Conversion rate is not clear
.IP \[bu] 2 .IP \[bu] 2
disturbs the accounting equation Disturbs the accounting equation, unless you add the --infer-equity flag
.PP .PP
You can prevent accidental implicit conversions due to a mistyped You can prevent accidental implicit conversions due to a mistyped
commodity symbol, by using \f[C]hledger check commodities\f[R]. commodity symbol, by using \f[C]hledger check commodities\f[R].
.PP
You can prevent implicit conversions entirely, by using You can prevent implicit conversions entirely, by using
\f[C]hledger check balancednoautoconversion\f[R], or \f[C]hledger check balancednoautoconversion\f[R], or
\f[C]-s/--strict\f[R]. \f[C]-s/--strict\f[R].
.SS Priced conversion .SS Conversion with explicit cost
.PP .PP
You can add the conversion rate using \[at] notation: You can add the conversion rate using \[at] notation:
.IP .IP
@ -1650,16 +1868,14 @@ Pro:
.IP \[bu] 2 .IP \[bu] 2
Still concise Still concise
.IP \[bu] 2 .IP \[bu] 2
makes the conversion rate clear Makes the conversion rate clear
.IP \[bu] 2 .IP \[bu] 2
provides some error checking Provides more error checking
.IP \[bu] 2
hledger can do cost reporting
.PP .PP
Con: Con:
.IP \[bu] 2 .IP \[bu] 2
Disturbs the accounting equation without the --infer-equity flag Disturbs the accounting equation, unless you add the --infer-equity flag
.SS Equity conversion .SS Conversion with equity postings
.PP .PP
In strict double entry bookkeeping, the above transaction is not In strict double entry bookkeeping, the above transaction is not
balanced in EUR or in USD, since some EUR disappears, and some USD balanced in EUR or in USD, since some EUR disappears, and some USD
@ -1684,24 +1900,22 @@ Pro:
.IP \[bu] 2 .IP \[bu] 2
Preserves the accounting equation Preserves the accounting equation
.IP \[bu] 2 .IP \[bu] 2
keeps track of conversions and related gains/losses in one place Keeps track of conversions and related gains/losses in one place
.IP \[bu] 2 .IP \[bu] 2
works in any double entry accounting system Standard, works in any double entry accounting system
.IP \[bu] 2
hledger can convert this to transaction prices using the --infer-costs
flag
.PP .PP
Con: Con:
.IP \[bu] 2 .IP \[bu] 2
More verbose More verbose
.IP \[bu] 2 .IP \[bu] 2
conversion rate is not clear Conversion rate is not obvious
.IP \[bu] 2 .IP \[bu] 2
depends on the order of postings Cost reporting requires adding the --infer-costs flag
.SS Priced equity conversion .SS Conversion with equity postings and explicit cost
.PP .PP
Another notation is to record both the conversion rate and the equity Here both equity postings and \[at] notation are used together.
postings: hledger will usually complain about this redundancy, but when using the
--infer-costs flag it is accepted.
.IP .IP
.nf .nf
\f[C] \f[C]
@ -1717,68 +1931,39 @@ Pro:
.IP \[bu] 2 .IP \[bu] 2
Preserves the accounting equation Preserves the accounting equation
.IP \[bu] 2 .IP \[bu] 2
keeps track of conversions and related gains/losses in one place Keeps track of conversions and related gains/losses in one place
.IP \[bu] 2 .IP \[bu] 2
makes the conversion rate clear Makes the conversion rate clear
.IP \[bu] 2 .IP \[bu] 2
provides some error checking Provides more error checking
.IP \[bu] 2
hledger can do cost reporting
.PP .PP
Con: Con:
.IP \[bu] 2 .IP \[bu] 2
Most verbose Most verbose
.IP \[bu] 2 .IP \[bu] 2
Requires --infer-costs flag Requires the --infer-costs flag
.IP \[bu] 2 .IP \[bu] 2
Not compatible with ledger Not compatible with ledger
.SS Inferring missing conversion rates .SS Cost tips
.PP
hledger will do this automatically for implicit conversions.
Currently it can not do this for equity conversions.
.SS Inferring missing equity postings
.PP
With the \f[C]--infer-equity\f[R] flag, hledger will add equity postings
to priced and implicit conversions.
.SS Inferring missing transaction prices from equity postings
.PP
With the \f[C]--infer-costs\f[R] flag, hledger will add transaction
prices from equity postings, and will be able to handle transaction
prices and equity postings together.
.SS Cost reporting
.PP
With the \f[C]-B/--cost\f[R] flag, hledger will convert the amounts in
priced and implicit conversions to their cost in the other commodity.
This is useful to see a report of what you paid for things (or how much
you sold things for).
Currently \f[C]-B/--cost\f[R] does not work on equity conversions, and
it disables \f[C]--infer-equity\f[R].
.PP
These operations are transient, only affecting reports.
If you want to change the journal file permanently, you could pipe each
entry through
\f[C]hledger -f- -I print [-x] [--infer-equity] [--infer-costs] [-B]\f[R]
.SS Conversion summary
.IP \[bu] 2 .IP \[bu] 2
Recording the conversion rate is good because it makes that clear and Recording the conversion rate explicitly is good because it makes that
allows cost reporting. clear and helps detect errors.
.IP \[bu] 2 .IP \[bu] 2
Recording equity postings is good because it balances the accounting Recording equity postings is good because it is correct bookkeeping and
equation and is correct bookkeeping. preserves the accounting equation.
.IP \[bu] 2 .IP \[bu] 2
Combining these is possible with the --infer-costs flag, but has certain Combining these is possible by using the --infer-costs flag (which
requirements for the order of postings. requires well-ordered postings).
.IP \[bu] 2 .IP \[bu] 2
When you want to see the cost (or sale proceeds) of things, use When you want to see the cost (or sale proceeds) of things, use
\f[C]-B/--cost\f[R]. \f[C]-B\f[R] (or \f[C]--cost\f[R]).
If you use equity conversion postings notation, use
\f[C]-B --infer-costs\f[R].
.IP \[bu] 2 .IP \[bu] 2
When you want to see a balanced balance sheet or correct journal If you use PTA cost notation, and you want to see a balanced balance
entries, use \f[C]--infer-equity\f[R]. sheet or print correct journal entries, use \f[C]--infer-equity\f[R].
.IP \[bu] 2 .IP \[bu] 2
\f[C]--cost\f[R] will remove any balancing equity posts, so as not to Conversion to cost is performed before valuation (described next).
disturb the accounting equation.
.IP \[bu] 2
Conversion/cost operations are performed before valuation.
.SH VALUATION .SH VALUATION
.PP .PP
Instead of reporting amounts in their original commodity, hledger can Instead of reporting amounts in their original commodity, hledger can
@ -6988,18 +7173,30 @@ number, eg 0.5 displayed with zero decimal places is \[dq]0\[dq]).
hledger was built with Decimal < 0.5.1.) hledger was built with Decimal < 0.5.1.)
.SS Transaction prices .SS Transaction prices
.PP .PP
Within a transaction, you can note an amount\[aq]s price in another (AKA Costs)
commodity.
This can be used to document the cost (in a purchase) or selling price
(in a sale).
For example, transaction prices are useful to record purchases of a
foreign currency.
Note transaction prices are fixed at the time of the transaction, and do
not change over time.
See also market prices, which represent prevailing exchange rates on a
certain date.
.PP .PP
There are several ways to record a transaction price: After a posting amount, you can note its cost or selling price in
another commodity, by writing either \f[C]\[at] UNITPRICE\f[R] or
\f[C]\[at]\[at] TOTALPRICE\f[R] after it.
This indicates a conversion transaction, where one commodity is
exchanged for another.
.PP
hledger docs have historically called this a \[dq]transaction price\[dq]
because it is specific to one transaction, unlike market prices which
are not.
\[dq]Cost\[dq] is shorter and might be preferable; just remember this
feature can represent either a buyer\[aq]s cost, or a seller\[aq]s
price.
.PP
Costs are usually written explicitly with \f[C]\[at]\f[R] or
\f[C]\[at]\[at]\f[R], but can also be inferred automatically for simple
multi-commodity transactions.
.PD 0
.P
.PD
As an example, here are several ways to record purchases of a foreign
currency in hledger, using the cost notation either explicitly or
implicitly:
.IP "1." 3 .IP "1." 3
Write the price per unit, as \f[C]\[at] UNITPRICE\f[R] after the amount: Write the price per unit, as \f[C]\[at] UNITPRICE\f[R] after the amount:
.RS 4 .RS 4
@ -7046,131 +7243,8 @@ Like 1, but the \f[C]\[at]\f[R] is parenthesised, i.e.
Like 2, but as in 4 the \f[C]\[at]\[at]\f[R] is parenthesised, i.e. Like 2, but as in 4 the \f[C]\[at]\[at]\f[R] is parenthesised, i.e.
\f[C](\[at]\[at])\f[R]; in hledger, this is equivalent to 2. \f[C](\[at]\[at])\f[R]; in hledger, this is equivalent to 2.
.PP .PP
Use the \f[C]-B/--cost\f[R] flag to convert amounts to their transaction Amounts can be converted to cost at report time using the
price\[aq]s commodity, if any. \f[C]-B/--cost\f[R] flag; this is discussed more in the COST section.
(mnemonic: \[dq]B\[dq] is from \[dq]cost Basis\[dq], as in Ledger).
Eg here is how -B affects the balance report for the example above:
.IP
.nf
\f[C]
$ hledger bal -N --flat
$-135 assets:dollars
\[Eu]100 assets:euros
$ hledger bal -N --flat -B
$-135 assets:dollars
$135 assets:euros # <- the euros\[aq] cost
\f[R]
.fi
.PP
Note -B is sensitive to the order of postings when a transaction price
is inferred: the inferred price will be in the commodity of the last
amount.
So if example 3\[aq]s postings are reversed, while the transaction is
equivalent, -B shows something different:
.IP
.nf
\f[C]
2009/1/1
assets:dollars $-135 ; 135 dollars sold
assets:euros \[Eu]100 ; for 100 euros
\f[R]
.fi
.IP
.nf
\f[C]
$ hledger bal -N --flat -B
\[Eu]-100 assets:dollars # <- the dollars\[aq] selling price
\[Eu]100 assets:euros
\f[R]
.fi
.SS Equity conversion postings
.PP
Transaction prices can be converted to and from equity conversion
postings using the \f[C]--infer-equity\f[R] and \f[C]--infer-costs\f[R]
flags.
.PP
With \f[C]--infer-equity\f[R], hledger will add equity postings to
balance out any transaction prices.
.IP
.nf
\f[C]
2009/1/1
assets:euros \[Eu]100 \[at] $1.35 ; 100 euros bought
assets:dollars -$135 ; for $135
\f[R]
.fi
.IP
.nf
\f[C]
$ hledger print --infer-equity
2009-01-01
assets:euros \[Eu]100 \[at] $1.35 ; 100 euros bought
equity:conversion:$-\[Eu]:\[Eu] \[Eu]-100 ; 100 euros bought, generated-posting:
equity:conversion:$-\[Eu]:$ $135.00 ; 100 euros bought, generated-posting:
assets:dollars $-135 ; for $135
\f[R]
.fi
.PP
The reverse is possible using \f[C]--infer-costs\f[R], which will check
any equity conversion postings and generate a transaction price for the
\f[I]first\f[R] non-conversion posting which matches.
.IP
.nf
\f[C]
2009-01-01
assets:euros \[Eu]100 ; 100 euros bought
equity:conversion \[Eu]-100
equity:conversion $135
assets:dollars $-135 ; for $135
\f[R]
.fi
.IP
.nf
\f[C]
$ hledger print --infer-costs
2009-01-01
assets:euros \[Eu]100 \[at]\[at] $135 ; 100 euros bought
equity:conversion \[Eu]-100
equity:conversion $135
assets:dollars $-135 ; for $135
\f[R]
.fi
.PP
Note that the above will assign the transaction price to the first
matching posting in the transaction.
If you want to assign it to a different posting, or if you have several
different sets of conversion postings which must match different
postings, you must manually specify the transaction price.
If you do this, equity conversion postings must occur in adjacent pairs
and must exactly match the amount of a non-conversion posting.
.IP
.nf
\f[C]
2009-01-01
assets:dollars $-135 ; $135 paid
equity:conversion \[Eu]-100
equity:conversion $135
assets:euros \[Eu]100 \[at]\[at] $135 ; to buy 100 euros
\f[R]
.fi
.IP
.nf
\f[C]
2009-01-01
assets:euros \[Eu]100 \[at] $1.35 ; 100 euros bought
equity:conversion \[Eu]-100
equity:conversion $135
assets:pounds \[Po]80 \[at]\[at] $100 ; 80 pounds bought
equity:conversion \[Po]-80
equity:conversion $100
assets:dollars $-235 ; for $235 total
\f[R]
.fi
.PP
The account names used for the conversion accounts can be changed with
the conversion account type declaration.
.SS Lot prices, lot dates .SS Lot prices, lot dates
.PP .PP
Ledger allows another kind of price, lot price (four variants: Ledger allows another kind of price, lot price (four variants:
@ -8113,7 +8187,7 @@ or, it can be (these are used less often):
assets for the cashflow report) assets for the cashflow report)
.IP \[bu] 2 .IP \[bu] 2
\f[C]V\f[R] or \f[C]Conversion\f[R] (a subtype of Equity, for \f[C]V\f[R] or \f[C]Conversion\f[R] (a subtype of Equity, for
conversions (see CONVERSION & COST).) conversions (see COST).)
.PP .PP
Here is a typical set of account type declarations: Here is a typical set of account type declarations:
.IP .IP
@ -10933,7 +11007,7 @@ Show only asset and liability balances, as a flat list, limited to depth
.IP .IP
.nf .nf
\f[C] \f[C]
$ hledger bal assets liabilities --flat -2 $ hledger bal assets liabilities -2
$4000 assets:bank $4000 assets:bank
$105 assets:cash $105 assets:cash
$-50 liabilities:creditcard $-50 liabilities:creditcard
@ -10947,7 +11021,7 @@ balance sheet:
.IP .IP
.nf .nf
\f[C] \f[C]
$ hledger bs --flat -2 $ hledger bs -2
Balance Sheet 2020-01-16 Balance Sheet 2020-01-16
|| 2020-01-16 || 2020-01-16

View File

@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
name: hledger name: hledger
version: 1.26.99 version: 1.27.1
synopsis: Command-line interface for the hledger accounting system synopsis: Command-line interface for the hledger accounting system
description: The command-line interface for the hledger accounting system. description: The command-line interface for the hledger accounting system.
Its basic function is to read a plain text file describing Its basic function is to read a plain text file describing
@ -134,7 +134,7 @@ library
other-modules: other-modules:
Paths_hledger Paths_hledger
ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind -optP-Wno-nonportable-include-path ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind -optP-Wno-nonportable-include-path
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
build-depends: build-depends:
Decimal >=0.5.1 Decimal >=0.5.1
, Diff >=0.2 , Diff >=0.2
@ -152,7 +152,7 @@ library
, githash >=0.1.6.1 , githash >=0.1.6.1
, hashable >=1.2.4 , hashable >=1.2.4
, haskeline >=0.6 , haskeline >=0.6
, hledger-lib >=1.26.99 && <1.27 , hledger-lib >=1.27.1 && <1.28
, lucid , lucid
, math-functions >=0.3.3.0 , math-functions >=0.3.3.0
, megaparsec >=7.0.0 && <9.3 , megaparsec >=7.0.0 && <9.3
@ -186,7 +186,7 @@ executable hledger
hs-source-dirs: hs-source-dirs:
app app
ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind -optP-Wno-nonportable-include-path ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind -optP-Wno-nonportable-include-path
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
build-depends: build-depends:
Decimal >=0.5.1 Decimal >=0.5.1
, aeson >=1 , aeson >=1
@ -203,7 +203,7 @@ executable hledger
, githash >=0.1.6.1 , githash >=0.1.6.1
, haskeline >=0.6 , haskeline >=0.6
, hledger , hledger
, hledger-lib >=1.26.99 && <1.27 , hledger-lib >=1.27.1 && <1.28
, math-functions >=0.3.3.0 , math-functions >=0.3.3.0
, megaparsec >=7.0.0 && <9.3 , megaparsec >=7.0.0 && <9.3
, microlens >=0.4 , microlens >=0.4
@ -237,7 +237,7 @@ test-suite unittest
hs-source-dirs: hs-source-dirs:
test test
ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind -optP-Wno-nonportable-include-path ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures -Wno-orphans -Wno-type-defaults -Wno-unused-do-bind -optP-Wno-nonportable-include-path
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
build-depends: build-depends:
Decimal >=0.5.1 Decimal >=0.5.1
, aeson >=1 , aeson >=1
@ -254,7 +254,7 @@ test-suite unittest
, githash >=0.1.6.1 , githash >=0.1.6.1
, haskeline >=0.6 , haskeline >=0.6
, hledger , hledger
, hledger-lib >=1.26.99 && <1.27 , hledger-lib >=1.27.1 && <1.28
, math-functions >=0.3.3.0 , math-functions >=0.3.3.0
, megaparsec >=7.0.0 && <9.3 , megaparsec >=7.0.0 && <9.3
, microlens >=0.4 , microlens >=0.4
@ -303,7 +303,7 @@ benchmark bench
, githash >=0.1.6.1 , githash >=0.1.6.1
, haskeline >=0.6 , haskeline >=0.6
, hledger , hledger
, hledger-lib >=1.26.99 && <1.27 , hledger-lib >=1.27.1 && <1.28
, html , html
, math-functions >=0.3.3.0 , math-functions >=0.3.3.0
, megaparsec >=7.0.0 && <9.3 , megaparsec >=7.0.0 && <9.3

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ HLEDGER(1) hledger User Manuals HLEDGER(1)
NAME NAME
This is the command-line interface (CLI) for the hledger accounting This is the command-line interface (CLI) for the hledger accounting
tool. Here we also describe hledger's concepts and file formats. This tool. Here we also describe hledger's concepts and file formats. This
manual is for hledger 1.26.99. manual is for hledger 1.27.
SYNOPSIS SYNOPSIS
hledger hledger
@ -1054,35 +1054,194 @@ QUERIES
this changed in hledger 1.22, previously it was the reverse, see the this changed in hledger 1.22, previously it was the reverse, see the
discussion at #1625. discussion at #1625.
CONVERSION & COST COST
This section is about converting between commodities. Some defini- This section is about recording the cost of things, in transactions
tions: where one commodity is exchanged for another. Eg an exchange of cur-
rency, or a stock purchase or sale. First, a quick glossary:
o A "commodity conversion" is an exchange of one currency or commodity o Conversion - an exchange of one currency or commodity for another.
for another. Eg a foreign currency exchange, or a purchase or sale Eg a foreign currency exchange, or a purchase or sale of stock or
of stock or cryptocurrency. cryptocurrency.
o A "conversion transaction" is a transaction involving one or more o Conversion transaction - a transaction involving one or more conver-
such conversions. sions.
o "Conversion rate" is the exchange rate in a conversion - the cost per o Conversion rate - the cost per unit of one commodity in the other, ie
unit of one commodity in the other. the exchange rate.
o "Cost" is how much of one commodity was paid to acquire the other o Cost - how much of one commodity was paid to acquire the other. And
(when buying), or how much was received in exchange for the other more generally, in hledger docs: the amount exchanged in the "sec-
(when selling). We call both of these "cost" for convenience (after ondary" commodity (usually your base currency), whether in a purchase
all, it is cost for one party or the other). or a sale, and whether expressed per unit or in total. Or, the @/@@
notation used to represent this.
Recording conversions o Transaction price - another name for the cost expressed with
As a concrete example, let's assume 100 EUR was converted to 120 USD. hledger's cost notation.
There are several ways to record this in the journal, each with pros
and cons which will be explained in more detail below. (Also, these
examples use journal format which is properly explained much further
below; sorry about that, you may want to read some of that first.)
Implicit conversion -B: Convert to cost
You can just record the outflow (100 EUR) and inflow (120 USD) in the As discussed a little further on in Transaction prices, when recording
appropriate asset account: a transaction you can also record the amount's cost in another commod-
ity, by adding @ UNITPRICE or @@ TOTALPRICE.
Then you can see a report with amounts converted to cost, by adding the
-B/--cost flag. (Mnemonic: "B" from "cost Basis", as in Ledger). Eg:
2022-01-01
assets:dollars $-135 ; 135 dollars is exchanged for..
assets:euros EUR100 @ $1.35 ; one hundred euros purchased at $1.35 each
$ hledger bal -N
$-135 assets:dollars
EUR100 assets:euros
$ hledger bal -N -B
$-135 assets:dollars
$135 assets:euros # <- the euros' cost
Notes:
-B is sensitive to the order of postings when a transaction price is
inferred: the inferred price will be in the commodity of the last
amount. So if example 3's postings are reversed, while the transaction
is equivalent, -B shows something different:
2022-01-01
assets:dollars $-135 ; 135 dollars sold
assets:euros EUR100 ; for 100 euros
$ hledger bal -N -B
EUR-100 assets:dollars # <- the dollars' selling price
EUR100 assets:euros
The @/@@ cost notation is convenient, but has some drawbacks: it does
not truly balance the transaction, so it disrupts the accounting equa-
tion and tends to causes a non-zero total in balance reports.
Equity conversion postings
By contrast, conventional double entry bookkeeping (DEB) uses a differ-
ent notation: an extra pair of equity postings to balance conversion
transactions. In this style, the above entry might be written:
2022-01-01 one hundred euros purchased at $1.35 each
assets:dollars $-135
equity:conversion $135
equity:conversion EUR-100
assets:euros EUR100
This style is more correct, but it's also more verbose and makes cost
reporting more difficult for PTA tools.
Happily, current hledger can read either notation, or convert one to
the other when needed, so you can use the one you prefer.
Inferring equity postings from cost
With --infer-equity, hledger detects transactions written with PTA cost
notation and adds equity conversion postings to them (and temporarily
permits the coexistence of equity conversion postings and cost nota-
tion, which normally would cause an unbalanced transaction error). Eg:
2022-01-01
assets:dollars -$135
assets:euros EUR100 @ $1.35
$ hledger print --infer-equity
2022-01-01
assets:dollars $-135
assets:euros EUR100 @ $1.35
equity:conversion:$-EUR:EUR EUR-100 ; generated-posting:
equity:conversion:$-EUR:$ $135.00 ; generated-posting:
The conversion account names can be changed with the conversion account
type declaration.
--infer-equity is useful when when transactions have been recorded
using PTA cost notation, to help preserve the accounting equation and
balance reports' zero total, or to produce more conventional journal
entries for sharing with non-PTA-users.
Experimental
Inferring cost from equity postings
The reverse operation is possible using --infer-costs, which detects
transactions written with equity conversion postings and adds PTA cost
notation to them (and temporarily permits the coexistence of equity
conversion postings and cost notation). Eg:
2022-01-01
assets:dollars $-135
equity:conversion $135
equity:conversion EUR-100
assets:euros EUR100
$ hledger print --infer-costs
2022-01-01
assets:dollars $-135 @@ EUR100
equity:conversion $135
equity:conversion EUR-100
assets:euros EUR100
--infer-costs is useful when combined with -B/--cost, allowing cost
reporting even when transactions have been recorded using equity post-
ings:
$ hledger print --infer-costs -B
2009-01-01
assets:dollars EUR-100
assets:euros EUR100
Notes:
Postings will be recognised as equity conversion postings if they are
1. to account(s) declared with type V (Conversion; or if no such
accounts are declared, accounts named equity:conversion, equity:trade,
equity:trading, or subaccounts of these) 2. adjacent 3. and exactly
matching the amounts of two non-conversion postings.
The total cost is appended to the first matching posting in the trans-
action. If you need to assign it to a different posting, or if you
have several different sets of conversion postings in one transaction,
you may need to write the costs explicitly yourself. Eg:
2022-01-01
assets:dollars $-135
equity:conversion EUR-100
equity:conversion $135
assets:euros EUR100 @@ $135
or:
2022-01-01
assets:dollars $-235
assets:euros EUR100 @ $1.35 ; 100 euros bought for $1.35 each
equity:conversion EUR-100
equity:conversion $135
assets:pounds 80 @@ $100 ; 80 pounds bought for $100 total
equity:conversion -80
equity:conversion $100
--infer-equity and --infer-costs can be used together, eg if you have a
mixture of both notations.
Experimental
When to infer cost/equity
Inferring equity postings or costs is still fairly new, so not enabled
by default. We're not sure yet if that should change. Here are two
suggestions to try, experience reports welcome:
1. When you use -B, always use --infer-costs as well. Eg: hledger bal
-B --infer-costs
2. Always run hledger with both flags enabled. Eg: alias hl="hledger
--infer-equity --infer-costs"
How to record conversions
Essentially there are four ways to record a conversion transaction in
hledger. Here are all of them, with pros and cons.
Conversion with implicit cost
Let's assume 100 EUR is converted to 120 USD. You can just record the
outflow (100 EUR) and inflow (120 USD) in the appropriate asset
account:
2021-01-01 2021-01-01
assets:cash -100 EUR assets:cash -100 EUR
@ -1094,25 +1253,25 @@ CONVERSION & COST
Pro: Pro:
o Easy, concise o Concise, easy
o hledger can do cost reporting
Con: Con:
o Less error checking - typos in amounts or commodity symbols may not o Less error checking - typos in amounts or commodity symbols may not
be detected be detected
o conversion rate is not clear o Conversion rate is not clear
o disturbs the accounting equation o Disturbs the accounting equation, unless you add the --infer-equity
flag
You can prevent accidental implicit conversions due to a mistyped com- You can prevent accidental implicit conversions due to a mistyped com-
modity symbol, by using hledger check commodities. You can prevent modity symbol, by using hledger check commodities.
implicit conversions entirely, by using hledger check balancednoauto-
conversion, or -s/--strict.
Priced conversion You can prevent implicit conversions entirely, by using hledger check
balancednoautoconversion, or -s/--strict.
Conversion with explicit cost
You can add the conversion rate using @ notation: You can add the conversion rate using @ notation:
2021-01-01 2021-01-01
@ -1126,17 +1285,16 @@ CONVERSION & COST
o Still concise o Still concise
o makes the conversion rate clear o Makes the conversion rate clear
o provides some error checking o Provides more error checking
o hledger can do cost reporting
Con: Con:
o Disturbs the accounting equation without the --infer-equity flag o Disturbs the accounting equation, unless you add the --infer-equity
flag
Equity conversion Conversion with equity postings
In strict double entry bookkeeping, the above transaction is not bal- In strict double entry bookkeeping, the above transaction is not bal-
anced in EUR or in USD, since some EUR disappears, and some USD anced in EUR or in USD, since some EUR disappears, and some USD
appears. This violates the accounting equation (A+L+E=0), and prevents appears. This violates the accounting equation (A+L+E=0), and prevents
@ -1155,24 +1313,22 @@ CONVERSION & COST
o Preserves the accounting equation o Preserves the accounting equation
o keeps track of conversions and related gains/losses in one place o Keeps track of conversions and related gains/losses in one place
o works in any double entry accounting system o Standard, works in any double entry accounting system
o hledger can convert this to transaction prices using the --infer-
costs flag
Con: Con:
o More verbose o More verbose
o conversion rate is not clear o Conversion rate is not obvious
o depends on the order of postings o Cost reporting requires adding the --infer-costs flag
Priced equity conversion Conversion with equity postings and explicit cost
Another notation is to record both the conversion rate and the equity Here both equity postings and @ notation are used together. hledger
postings: will usually complain about this redundancy, but when using the
--infer-costs flag it is accepted.
2021-01-01 2021-01-01
assets:cash -100 EUR @ 1.20 USD assets:cash -100 EUR @ 1.20 USD
@ -1184,66 +1340,38 @@ CONVERSION & COST
o Preserves the accounting equation o Preserves the accounting equation
o keeps track of conversions and related gains/losses in one place o Keeps track of conversions and related gains/losses in one place
o makes the conversion rate clear o Makes the conversion rate clear
o provides some error checking o Provides more error checking
o hledger can do cost reporting
Con: Con:
o Most verbose o Most verbose
o Requires --infer-costs flag o Requires the --infer-costs flag
o Not compatible with ledger o Not compatible with ledger
Inferring missing conversion rates Cost tips
hledger will do this automatically for implicit conversions. Currently o Recording the conversion rate explicitly is good because it makes
it can not do this for equity conversions. that clear and helps detect errors.
Inferring missing equity postings o Recording equity postings is good because it is correct bookkeeping
With the --infer-equity flag, hledger will add equity postings to and preserves the accounting equation.
priced and implicit conversions.
Inferring missing transaction prices from equity postings o Combining these is possible by using the --infer-costs flag (which
With the --infer-costs flag, hledger will add transaction prices from requires well-ordered postings).
equity postings, and will be able to handle transaction prices and
equity postings together.
Cost reporting o When you want to see the cost (or sale proceeds) of things, use -B
With the -B/--cost flag, hledger will convert the amounts in priced and (or --cost). If you use equity conversion postings notation, use -B
implicit conversions to their cost in the other commodity. This is --infer-costs.
useful to see a report of what you paid for things (or how much you
sold things for). Currently -B/--cost does not work on equity conver-
sions, and it disables --infer-equity.
These operations are transient, only affecting reports. If you want to o If you use PTA cost notation, and you want to see a balanced balance
change the journal file permanently, you could pipe each entry through sheet or print correct journal entries, use --infer-equity.
hledger -f- -I print [-x] [--infer-equity] [--infer-costs] [-B]
Conversion summary o Conversion to cost is performed before valuation (described next).
o Recording the conversion rate is good because it makes that clear and
allows cost reporting.
o Recording equity postings is good because it balances the accounting
equation and is correct bookkeeping.
o Combining these is possible with the --infer-costs flag, but has cer-
tain requirements for the order of postings.
o When you want to see the cost (or sale proceeds) of things, use
-B/--cost.
o When you want to see a balanced balance sheet or correct journal
entries, use --infer-equity.
o --cost will remove any balancing equity posts, so as not to disturb
the accounting equation.
o Conversion/cost operations are performed before valuation.
VALUATION VALUATION
Instead of reporting amounts in their original commodity, hledger can Instead of reporting amounts in their original commodity, hledger can
@ -1587,15 +1715,14 @@ VALUATION
posting cost value at value at posting value at value at posting cost value at value at posting value at value at
amounts report end date report or DATE/today amounts report end date report or DATE/today
or today journal end or today journal end
balance unchanged unchanged unchanged unchanged unchanged balance unchanged unchanged unchanged unchanged unchanged
asser- asser-
tions/assign- tions/assign-
ments ments
register register
starting bal- cost value at valued at day value at value at starting bal- cost value at valued at day value at value at
ance (-H) report or each historical report or DATE/today ance (-H) report or each historical report or DATE/today
journal end posting was made journal end journal end posting was made journal end
@ -1658,8 +1785,6 @@ VALUATION
row averages ages of dis- ages of dis- displayed values ages of dis- ages of dis- row averages ages of dis- ages of dis- displayed values ages of dis- ages of dis-
(-T, -A) played val- played val- played val- played values (-T, -A) played val- played val- played val- played values
ues ues ues ues ues ues
column totals sums of dis- sums of dis- sums of displayed sums of dis- sums of dis- column totals sums of dis- sums of dis- sums of displayed sums of dis- sums of dis-
played val- played val- values played val- played values played val- played val- values played val- played values
ues ues ues ues ues ues
@ -1798,8 +1923,6 @@ OUTPUT
balance Y 1 Y 1 Y 1,2 Y balance Y 1 Y 1 Y 1,2 Y
bal- Y 1 Y 1 Y 1 Y bal- Y 1 Y 1 Y 1 Y
ancesheet ancesheet
bal- Y 1 Y 1 Y 1 Y bal- Y 1 Y 1 Y 1 Y
ancesheete- ancesheete-
quity quity
@ -5023,15 +5146,23 @@ JOURNAL FORMAT
this could vary if hledger was built with Decimal < 0.5.1.) this could vary if hledger was built with Decimal < 0.5.1.)
Transaction prices Transaction prices
Within a transaction, you can note an amount's price in another commod- (AKA Costs)
ity. This can be used to document the cost (in a purchase) or selling
price (in a sale). For example, transaction prices are useful to
record purchases of a foreign currency. Note transaction prices are
fixed at the time of the transaction, and do not change over time. See
also market prices, which represent prevailing exchange rates on a cer-
tain date.
There are several ways to record a transaction price: After a posting amount, you can note its cost or selling price in
another commodity, by writing either @ UNITPRICE or @@ TOTALPRICE after
it. This indicates a conversion transaction, where one commodity is
exchanged for another.
hledger docs have historically called this a "transaction price"
because it is specific to one transaction, unlike market prices which
are not. "Cost" is shorter and might be preferable; just remember this
feature can represent either a buyer's cost, or a seller's price.
Costs are usually written explicitly with @ or @@, but can also be
inferred automatically for simple multi-commodity transactions.
As an example, here are several ways to record purchases of a foreign
currency in hledger, using the cost notation either explicitly or
implicitly:
1. Write the price per unit, as @ UNITPRICE after the amount: 1. Write the price per unit, as @ UNITPRICE after the amount:
@ -5059,92 +5190,8 @@ JOURNAL FORMAT
5. Like 2, but as in 4 the @@ is parenthesised, i.e. (@@); in hledger, 5. Like 2, but as in 4 the @@ is parenthesised, i.e. (@@); in hledger,
this is equivalent to 2. this is equivalent to 2.
Use the -B/--cost flag to convert amounts to their transaction price's Amounts can be converted to cost at report time using the -B/--cost
commodity, if any. (mnemonic: "B" is from "cost Basis", as in Ledger). flag; this is discussed more in the COST section.
Eg here is how -B affects the balance report for the example above:
$ hledger bal -N --flat
$-135 assets:dollars
EUR100 assets:euros
$ hledger bal -N --flat -B
$-135 assets:dollars
$135 assets:euros # <- the euros' cost
Note -B is sensitive to the order of postings when a transaction price
is inferred: the inferred price will be in the commodity of the last
amount. So if example 3's postings are reversed, while the transaction
is equivalent, -B shows something different:
2009/1/1
assets:dollars $-135 ; 135 dollars sold
assets:euros EUR100 ; for 100 euros
$ hledger bal -N --flat -B
EUR-100 assets:dollars # <- the dollars' selling price
EUR100 assets:euros
Equity conversion postings
Transaction prices can be converted to and from equity conversion post-
ings using the --infer-equity and --infer-costs flags.
With --infer-equity, hledger will add equity postings to balance out
any transaction prices.
2009/1/1
assets:euros EUR100 @ $1.35 ; 100 euros bought
assets:dollars -$135 ; for $135
$ hledger print --infer-equity
2009-01-01
assets:euros EUR100 @ $1.35 ; 100 euros bought
equity:conversion:$-EUR:EUR EUR-100 ; 100 euros bought, generated-posting:
equity:conversion:$-EUR:$ $135.00 ; 100 euros bought, generated-posting:
assets:dollars $-135 ; for $135
The reverse is possible using --infer-costs, which will check any
equity conversion postings and generate a transaction price for the
first non-conversion posting which matches.
2009-01-01
assets:euros EUR100 ; 100 euros bought
equity:conversion EUR-100
equity:conversion $135
assets:dollars $-135 ; for $135
$ hledger print --infer-costs
2009-01-01
assets:euros EUR100 @@ $135 ; 100 euros bought
equity:conversion EUR-100
equity:conversion $135
assets:dollars $-135 ; for $135
Note that the above will assign the transaction price to the first
matching posting in the transaction. If you want to assign it to a
different posting, or if you have several different sets of conversion
postings which must match different postings, you must manually specify
the transaction price. If you do this, equity conversion postings must
occur in adjacent pairs and must exactly match the amount of a non-con-
version posting.
2009-01-01
assets:dollars $-135 ; $135 paid
equity:conversion EUR-100
equity:conversion $135
assets:euros EUR100 @@ $135 ; to buy 100 euros
2009-01-01
assets:euros EUR100 @ $1.35 ; 100 euros bought
equity:conversion EUR-100
equity:conversion $135
assets:pounds 80 @@ $100 ; 80 pounds bought
equity:conversion -80
equity:conversion $100
assets:dollars $-235 ; for $235 total
The account names used for the conversion accounts can be changed with
the conversion account type declaration.
Lot prices, lot dates Lot prices, lot dates
Ledger allows another kind of price, lot price (four variants: {UNIT- Ledger allows another kind of price, lot price (four variants: {UNIT-
@ -5402,9 +5449,6 @@ JOURNAL FORMAT
any text, ignored. any text, ignored.
alias Rewrites account names, in following entries until end of Y alias Rewrites account names, in following entries until end of Y
current file or end aliases. current file or end aliases.
apply Prepends a common parent account to all account names, in Y apply Prepends a common parent account to all account names, in Y
account following entries until end of current file or end apply account following entries until end of current file or end apply
account. account.
@ -5802,8 +5846,7 @@ JOURNAL FORMAT
o C or Cash (a subtype of Asset, indicating liquid assets for the cash- o C or Cash (a subtype of Asset, indicating liquid assets for the cash-
flow report) flow report)
o V or Conversion (a subtype of Equity, for conversions (see CONVERSION o V or Conversion (a subtype of Equity, for conversions (see COST).)
& COST).)
Here is a typical set of account type declarations: Here is a typical set of account type declarations:
@ -6388,8 +6431,6 @@ CSV FORMAT
below, after the examples: below, after the examples:
skip skip one or more header lines or matched CSV skip skip one or more header lines or matched CSV
records records
fields list name CSV fields, assign them to hledger fields list name CSV fields, assign them to hledger
@ -7922,7 +7963,7 @@ COMMON TASKS
Show only asset and liability balances, as a flat list, limited to Show only asset and liability balances, as a flat list, limited to
depth 2: depth 2:
$ hledger bal assets liabilities --flat -2 $ hledger bal assets liabilities -2
$4000 assets:bank $4000 assets:bank
$105 assets:cash $105 assets:cash
$-50 liabilities:creditcard $-50 liabilities:creditcard
@ -7932,7 +7973,7 @@ COMMON TASKS
Show the same thing without negative numbers, formatted as a simple Show the same thing without negative numbers, formatted as a simple
balance sheet: balance sheet:
$ hledger bs --flat -2 $ hledger bs -2
Balance Sheet 2020-01-16 Balance Sheet 2020-01-16
|| 2020-01-16 || 2020-01-16
@ -8114,4 +8155,4 @@ SEE ALSO
hledger-1.26.99 August 2022 HLEDGER(1) hledger-1.27 September 2022 HLEDGER(1)

View File

@ -1,5 +1,5 @@
name: hledger name: hledger
version: 1.26.99 version: 1.27.1
synopsis: Command-line interface for the hledger accounting system synopsis: Command-line interface for the hledger accounting system
description: | description: |
The command-line interface for the hledger accounting system. The command-line interface for the hledger accounting system.
@ -97,7 +97,7 @@ ghc-options:
dependencies: dependencies:
- base >=4.14 && <4.17 - base >=4.14 && <4.17
- hledger-lib >=1.26.99 && <1.27 - hledger-lib >=1.27.1 && <1.28
- aeson >=1 - aeson >=1
- ansi-terminal >=0.9 - ansi-terminal >=0.9
- breakpoint - breakpoint
@ -138,7 +138,7 @@ when:
- terminfo - terminfo
library: library:
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
exposed-modules: exposed-modules:
- Hledger.Cli - Hledger.Cli
- Hledger.Cli.Main - Hledger.Cli.Main
@ -187,7 +187,7 @@ executables:
hledger: hledger:
source-dirs: app source-dirs: app
main: hledger-cli.hs main: hledger-cli.hs
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
when: when:
- condition: flag(threaded) - condition: flag(threaded)
ghc-options: -threaded ghc-options: -threaded
@ -199,7 +199,7 @@ tests:
source-dirs: test source-dirs: test
main: unittest.hs main: unittest.hs
other-modules: [] # prevent double compilation, https://github.com/sol/hpack/issues/188 other-modules: [] # prevent double compilation, https://github.com/sol/hpack/issues/188
cpp-options: -DVERSION="1.26.99" cpp-options: -DVERSION="1.27.1"
dependencies: dependencies:
- hledger - hledger

View File

@ -1,6 +1,5 @@
# 1. # 1.
hledger -f sample.journal balance --tree $ hledger -f sample.journal balance --tree
>>>
$-1 assets $-1 assets
$1 bank:saving $1 bank:saving
$-2 cash $-2 cash
@ -13,22 +12,18 @@ hledger -f sample.journal balance --tree
$1 liabilities:debts $1 liabilities:debts
-------------------- --------------------
0 0
>>>=0
# 2. # 2.
hledger -f sample.journal balance --tree o $ hledger -f sample.journal balance --tree o
>>>
$1 expenses:food $1 expenses:food
$-2 income $-2 income
$-1 gifts $-1 gifts
$-1 salary $-1 salary
-------------------- --------------------
$-1 $-1
>>>=0
# 3. Period reporting works for a specific year # 3. Period reporting works for a specific year
hledger -f - balance -b 2016 -e 2017 -N <
<<<
2015/10/10 Client A | Invoice #1 2015/10/10 Client A | Invoice #1
assets:receivables $10,000.00 assets:receivables $10,000.00
revenue:clients:A -$10,000.00 revenue:clients:A -$10,000.00
@ -48,16 +43,13 @@ hledger -f - balance -b 2016 -e 2017 -N
2016/03/01 Deposit | Invoice #2 2016/03/01 Deposit | Invoice #2
assets:checking $10.00 assets:checking $10.00
assets:receivables -$10.00 assets:receivables -$10.00
>>> $ hledger -f - balance -b 2016 -e 2017 -N
$-40.00 assets:checking $-40.00 assets:checking
$50.00 expense:hosting $50.00 expense:hosting
$-10.00 revenue:clients:B $-10.00 revenue:clients:B
>>>2
>>>= 0
# 4. Period reporting works for two years # 4. Period reporting works for two years
hledger -f - balance --tree -b 2015 -e 2017 -N <
<<<
2015/10/10 Client A | Invoice #1 2015/10/10 Client A | Invoice #1
assets:receivables $10,000.00 assets:receivables $10,000.00
revenue:clients:A -$10,000.00 revenue:clients:A -$10,000.00
@ -77,18 +69,15 @@ hledger -f - balance --tree -b 2015 -e 2017 -N
2016/03/01 Deposit | Invoice #2 2016/03/01 Deposit | Invoice #2
assets:checking $10.00 assets:checking $10.00
assets:receivables -$10.00 assets:receivables -$10.00
>>> $ hledger -f - balance --tree -b 2015 -e 2017 -N
$9,960.00 assets:checking $9,960.00 assets:checking
$50.00 expense:hosting $50.00 expense:hosting
$-10,010.00 revenue:clients $-10,010.00 revenue:clients
$-10,000.00 A $-10,000.00 A
$-10.00 B $-10.00 B
>>>2
>>>= 0
# 5. Period reporting works for one month # 5. Period reporting works for one month
hledger -f - balance --tree -b 2015/11 -e 2015/12 -N <
<<<
2015/10/10 Client A | Invoice #1 2015/10/10 Client A | Invoice #1
assets:receivables $10,000.00 assets:receivables $10,000.00
revenue:clients:A -$10,000.00 revenue:clients:A -$10,000.00
@ -108,16 +97,13 @@ hledger -f - balance --tree -b 2015/11 -e 2015/12 -N
2016/03/01 Deposit | Invoice #2 2016/03/01 Deposit | Invoice #2
assets:checking $10.00 assets:checking $10.00
assets:receivables -$10.00 assets:receivables -$10.00
>>> $ hledger -f - balance --tree -b 2015/11 -e 2015/12 -N
0 assets 0 assets
$10,000.00 checking $10,000.00 checking
$-10,000.00 receivables $-10,000.00 receivables
>>>2
>>>= 0
# 6. Period reporting works for one month in another year # 6. Period reporting works for one month in another year
hledger -f - balance -b 2016/10 -e 2016/11 <
<<<
2015/10/10 Client A | Invoice #1 2015/10/10 Client A | Invoice #1
assets:receivables $10,000.00 assets:receivables $10,000.00
revenue:clients:A -$10,000.00 revenue:clients:A -$10,000.00
@ -137,88 +123,85 @@ hledger -f - balance -b 2016/10 -e 2016/11
2016/03/01 Deposit | Invoice #2 2016/03/01 Deposit | Invoice #2
assets:checking $10.00 assets:checking $10.00
assets:receivables -$10.00 assets:receivables -$10.00
>>> $ hledger -f - balance -b 2016/10 -e 2016/11
-------------------- --------------------
0 0
>>>2
>>>= 0
# 7. Default CSV output. # 7. Default CSV output.
hledger -f - balance -N --output-format=csv <
<<<
2021-01-01 Test 2021-01-01 Test
Assets:ABC "AB.C" 1 Assets:ABC "AB.C" 1
Assets:Cash -$1 Assets:Cash -$1
>>> $ hledger -f - balance -N --output-format=csv
"account","balance" "account","balance"
"Assets:ABC","""AB.C"" 1" "Assets:ABC","""AB.C"" 1"
"Assets:Cash","$-1" "Assets:Cash","$-1"
>>>= 0
# 8. CSV output always shows full account names, even in tree mode (#1565). # 8. CSV output always shows full account names, even in tree mode (#1565).
hledger -f - balance -N --output-format=csv --tree <
<<<
2021-01-01 Test 2021-01-01 Test
Assets:ABC "AB.C" 1 Assets:ABC "AB.C" 1
Assets:Cash -$1 Assets:Cash -$1
>>> $ hledger -f - balance -N --output-format=csv --tree
"account","balance" "account","balance"
"Assets","$-1, ""AB.C"" 1" "Assets","$-1, ""AB.C"" 1"
"Assets:ABC","""AB.C"" 1" "Assets:ABC","""AB.C"" 1"
"Assets:Cash","$-1" "Assets:Cash","$-1"
>>>= 0
# 9. CSV output always does not show thousands separators # 9. CSV output always does not show thousands separators
hledger -f - balance -N --output-format=csv <
<<<
2021-01-01 Test 2021-01-01 Test
Assets:ABC $10 000.00 Assets:ABC $10 000.00
Assets:Cash -$10 000.00 Assets:Cash -$10 000.00
>>> $ hledger -f - balance -N --output-format=csv
"account","balance" "account","balance"
"Assets:ABC","$10000.00" "Assets:ABC","$10000.00"
"Assets:Cash","$-10000.00" "Assets:Cash","$-10000.00"
>>>= 0
# 10. --declared includes all declared leaf accounts, even if they have no postings. # 10. --declared includes all declared leaf accounts, even if they have no postings.
# They are filtered, depth-clipped, and form trees like the others. # They are filtered, depth-clipped, and form trees like the others.
# (XXX Here a:ac is not declared and so not shown, even though normally a balance report clipped to depth 2 would show it. Wrong ?) # (XXX Here a:ac is not declared and so not shown, even though normally a balance report clipped to depth 2 would show it. Wrong ?)
hledger -f - balance -NE --declared --tree --depth 2 a <
<<<
account a account a
account a:aa account a:aa
account a:ab account a:ab
account a:ac:aca account a:ac:aca
account b account b
>>> $ hledger -f - balance -NE --declared --tree --depth 2 a
0 a 0 a
0 aa 0 aa
0 ab 0 ab
>>>= 0
# 11. In list mode we can see that non-leaf declared accounts are excluded. # 11. In list mode we can see that non-leaf declared accounts are excluded.
hledger -f - balance -NE --declared --flat <
<<<
account a account a
account a:aa account a:aa
account a:ab account a:ab
account a:ac:aca account a:ac:aca
account b account b
>>> $ hledger -f - balance -NE --declared --flat
0 a:aa 0 a:aa
0 a:ab 0 a:ab
0 a:ac:aca 0 a:ac:aca
0 b 0 b
>>>= 0
# 12. not:ACCT queries work with declared accounts. # 12. not:ACCT queries work with declared accounts.
hledger -f - balance -NE --declared not:a <
<<<
account a account a
account a:aa account a:aa
account a:ab account a:ab
account a:ac:aca account a:ac:aca
account b account b
>>> $ hledger -f - balance -NE --declared not:a
0 b 0 b
>>>= 0
# 13. An empty periodic report in HTML output does not break.
<
$ hledger -f- bal -M -O html
> //
# 14. An empty totals column in HTML output does not break (#1933).
<
$ hledger -f- bal -MT -O html
> //

View File

@ -1,5 +1,5 @@
# 1. all data files on the command line should be read # 1. all data files on the command line should be read
hledger inc -f personal.journal -f business.journal hledger is -f personal.journal -f business.journal
>>> >>>
Income Statement 2014-01-01..2014-01-02 Income Statement 2014-01-01..2014-01-02