Reseting a null balance to zero throws an error

276 views
Skip to first unread message

Guillaume Chéreau

unread,
Aug 5, 2015, 1:03:09 PM8/5/15
to Ledger
I know this has been mentioned before, but the following file:

2014-01-01 Adjust Balance
    Assets:PayPal               =       0.00 USD
    Equity:Opening

Does not parse correctly:

ledger -f test.dat b
While parsing file "/tmp/test/test.dat", line 4:
Error: Only one posting with null amount allowed per transaction

I think this is a bug.  I use this kind of entries so that I can split my accounting into one file per year.

thierry

unread,
Aug 8, 2015, 7:39:21 AM8/8/15
to Ledger
Error message sounds explicit for me: "Only one posting with null amount allowed per transaction"

So, the following should be used:


2014-01-01 Adjust Balance
    Assets:PayPal               =       0.00 USD


Best,
Thierry

thierry

unread,
Aug 8, 2015, 7:39:37 AM8/8/15
to Ledger
Error message sounds explicit for me: "Only one posting with null amount allowed per transaction"

So, the following should be used:

2014-01-01 Adjust Balance
    Assets:PayPal               =       0.00 USD


Best,
Thierry

On Wednesday, August 5, 2015 at 7:03:09 PM UTC+2, Guillaume Chéreau wrote:

Martin Blais

unread,
Aug 8, 2015, 1:17:49 PM8/8/15
to ledger-cli
This is another reason to separate out the balance assertions from transactions in Ledger's design.
The "transaction" here is only present to support a balance assertion, and users are confused as a result.
This would be less confusing if a separate directive existed.
In fact, you could argue that the 0 amount posting only pollutes the space of postings in order to support putting an assertion there.


--

---
You received this message because you are subscribed to the Google Groups "Ledger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ledger-cli+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

John Wiegley

unread,
Aug 8, 2015, 3:30:12 PM8/8/15
to ledge...@googlegroups.com
>>>>> Martin Blais <bl...@furius.ca> writes:

> This would be less confusing if a separate directive existed.

I like having balance assertions as a part of the posting specification, since
it ensures the "meaning" of the transaction is maintained even if I move it
around. More on this below.

However, it should be trivial to enhance the current "assert" directive to
assert something about the current state of accounts at any given point in the
data flow. For example:

assert account("Expenses:Martin").total == $200.00

This does not quite work today, because "account" is not in the session scope.
Ideally what we want is a short-hand for this notation called "balance" that
gives much more information on why things didn't balance.

balance Expenses:Martin $200.00

However, there are some inherent differences between these two approaches, and
as you know, I'm loathe to enforce a particular "way" just because I have a
certain use case in mind. Ledger is all about freedom to decide what your
ledgers mean, even if that freedom imposes some initial headaches.

For example, "posting-attached" balance assertions occur before automated
transactions are applied, which could be important for some users.

Further, it ties the assertion to the UID for the transaction, which allows
"split assertions": where the same transaction (i.e., the same UID) appears in
two separate files, with each copy asserting a different half of the
transaction.

I use this feature to keep Checking transactions with assertions in one file,
and credit card transactions with paired balance assertions in another file. A
separate "balance" directive would dissociate these pairs, making it very hard
to sync them up again after any major edits to the files (something that
happeans from time to time).

So, can we and should we support your use case? Certainly. Should we support
only that usage pattern? Absolutely not.

John

Martin Blais

unread,
Aug 8, 2015, 4:08:17 PM8/8/15
to ledger-cli
On Sat, Aug 8, 2015 at 3:30 PM, John Wiegley <jo...@newartisans.com> wrote:
>>>>> Martin Blais <bl...@furius.ca> writes:

> This would be less confusing if a separate directive existed.

I like having balance assertions as a part of the posting specification, since
it ensures the "meaning" of the transaction is maintained even if I move it
around. More on this below.

What do you mean by "the meaning"? I don't understand.


However, it should be trivial to enhance the current "assert" directive to
assert something about the current state of accounts at any given point in the
data flow. For example:

    assert account("Expenses:Martin").total == $200.00

This does not quite work today, because "account" is not in the session scope.
Ideally what we want is a short-hand for this notation called "balance" that
gives much more information on why things didn't balance.

    balance Expenses:Martin    $200.00

BTW, these only make sense as file-based assertions, and not date-based assertions.
(With date-based assertions, ordering does not matter.)


However, there are some inherent differences between these two approaches, and
as you know, I'm loathe to enforce a particular "way" just because I have a
certain use case in mind. Ledger is all about freedom to decide what your
ledgers mean, even if that freedom imposes some initial headaches.

For example, "posting-attached" balance assertions occur before automated
transactions are applied, which could be important for some users.

FWIW on a related note, the date-based assertions I implemented are applied _after_ interpolation and plugins are run. I've found it useful, but rarely, to verify some of the things that plugins do.


Further, it ties the assertion to the UID for the transaction, which allows
"split assertions": where the same transaction (i.e., the same UID) appears in
two separate files, with each copy asserting a different half of the
transaction.

I use this feature to keep Checking transactions with assertions in one file,
and credit card transactions with paired balance assertions in another file. A
separate "balance" directive would dissociate these pairs, making it very hard
to sync them up again after any major edits to the files (something that
happeans from time to time).

I don't see a problem with this if they were a separate directive. You would have one assertion directive in one file on one account (e.g. your checking account), and a different one in the other (on the other account, e.g. the credit card account). Why wouldn't that work? That's what I do with date-based balance assertions. I don't understand the problem you describe.




So, can we and should we support your use case? Certainly. Should we support
only that usage pattern? Absolutely not.

Liberating users from the order-dependent nature of their transactions and the associated problems is more of a gain (they would be able to organize their transactions any way they want) than the corresponding loss incurred by removing the possibility of order-dependent assertions.


John Wiegley

unread,
Aug 8, 2015, 4:51:43 PM8/8/15
to ledge...@googlegroups.com
>>>>> Martin Blais <bl...@furius.ca> writes:

> I like having balance assertions as a part of the posting specification,
> since
> it ensures the "meaning" of the transaction is maintained even if I move
> it
> around. More on this below.

> What do you mean by "the meaning"? I don't understand.

The meaning refers to "right here the balance is X". If I move the
transaction, that is no longer true. Perhaps "meaning" is the wrong word for
this.

> BTW, these only make sense as file-based assertions, and not date-based
> assertions. (With date-based assertions, ordering does not matter.)

Right, and I like file-based assertions.

> I don't see a problem with this if they were a separate directive. You would
> have one assertion directive in one file on one account (e.g. your checking
> account), and a different one in the other (on the other account, e.g. the
> credit card account). Why wouldn't that work? That's what I do with
> date-based balance assertions. I don't understand the problem you describe.

If I do it with assertions only, then I'm simply verifying that the balance of
certain accounts is X in two separate files. There is no connection that for a
*given transaction*, the balance of each side of the transfer ends up being an
exact amount.

> Liberating users from the order-dependent nature of their transactions and
> the associated problems is more of a gain (they would be able to organize
> their transactions any way they want) than the corresponding loss incurred
> by removing the possibility of order-dependent assertions.

If I could support both with equal simplicitly and speed, great, but until
then I prefer order-dependent assertions because they require fewer decisions
to be made within Ledger.

John

Martin Blais

unread,
Aug 8, 2015, 5:45:20 PM8/8/15
to ledger-cli
On Sat, Aug 8, 2015 at 4:51 PM, John Wiegley <jo...@newartisans.com> wrote:
>>>>> Martin Blais <bl...@furius.ca> writes:

>     I like having balance assertions as a part of the posting specification,
>     since
>     it ensures the "meaning" of the transaction is maintained even if I move
>     it
>     around. More on this below.

> What do you mean by "the meaning"? I don't understand.

The meaning refers to "right here the balance is X". If I move the
transaction, that is no longer true. Perhaps "meaning" is the wrong word for
this.

If I understand what you mean, by "right here" you mean, "the balance including the list of all transactions in this file up to this particular one, in file order."


> BTW, these only make sense as file-based assertions, and not date-based
> assertions. (With date-based assertions, ordering does not matter.)

Right, and I like file-based assertions.

> I don't see a problem with this if they were a separate directive. You would
> have one assertion directive in one file on one account (e.g. your checking
> account), and a different one in the other (on the other account, e.g. the
> credit card account). Why wouldn't that work? That's what I do with
> date-based balance assertions. I don't understand the problem you describe.

If I do it with assertions only, then I'm simply verifying that the balance of
certain accounts is X in two separate files. There is no connection that for a
*given transaction*, the balance of each side of the transfer ends up being an
exact amount.

Again, if I understand correctly, the only concern here is about assertions _within_ a day. Your concern is that dated assertions combined with an assumption of order-independence do not allow the user to assert an intra-day balance that occurs immediately after a particular transaction, where "after" means, in the order defined by the transactions as they are seen in the file. But the way you resolved this problem is by ignoring the dates so that you have a well-defined ordering that allows you to do intra-day assertions.

I like the idea of being able to make intra-day assertions too. But I find the compromise you've made intolerably unfavorable. Based on your design choice, the price to pay for that capability is 

- Moving declarations arbitrarily around becomes uncomfortably risky, if not sometimes impossible. 
- If some transactions affecting a particular account are missing from a particular file, the assertions are asserting numbers which do not match that account's real balance, it just includes the postings from that one file, unless the file is included before that assertion.
- The balances include postings with dates later than the date of the transaction with the assertion if they appear beforehand in the file.
- It's not intuitive, the natural interpretation users make is that the dates matter, but they don't.

The best way to understand it is that it's a single-pass system. For calculating assertions, the dates of transactions are effectively ignored. This confused me a while time ago when I tried out Ledger. IMO these drawbacks far, far outweigh the relatively tame benefits of being able to support intra-day balance assertions.

Examples in attachment.

assertions.lgr
assertions2.lgr

John Wiegley

unread,
Aug 8, 2015, 6:53:56 PM8/8/15
to ledge...@googlegroups.com
>>>>> Martin Blais <bl...@furius.ca> writes:

> If I understand what you mean, by "right here" you mean, "the balance
> including the list of all transactions in this file up to this particular
> one, in file order."

Yes.

> Again, if I understand correctly, the only concern here is about assertions
> _ within_ a day. Your concern is that dated assertions combined with an
> assumption of order-independence do not allow the user to assert an
> intra-day balance that occurs immediately after a particular transaction,
> where "after" means, in the order defined by the transactions as they are
> seen in the file. But the way you resolved this problem is by ignoring the
> dates so that you have a well-defined ordering that allows you to do
> intra-day assertions.

You could also have your days out of sequence. File-order is completely
independent from any notion of day-order.

> I like the idea of being able to make intra-day assertions too. But I find
> the compromise you've made intolerably unfavorable...

And this is why beancount exists. :)

> The best way to understand it is that it's a single-pass system. For
> calculating assertions, the dates of transactions are effectively ignored.

Yes!

> This confused me a while time ago when I tried out Ledger. IMO these
> drawbacks far, far outweigh the relatively tame benefits of being able to
> support intra-day balance assertions.

We agree to disagree, until I find a solution that makes us both happy without
undo costs in either direction.

John

Guillaume Chéreau

unread,
Sep 8, 2015, 3:27:47 AM9/8/15
to Ledger, jo...@newartisans.com
I am not sure I understand the whole thread, but I would like to reiterate my problem, because I am working on my accounting files now and I am still having issues.

So I keep one ledger file per fiscal year for my business: 2013.dat, 2014.dat, 2015.dat etc...

The first entry of each file set the amount of money I have at the beginning of the year.  For example it could be:

2015-01-01 Initial balance
    HSBC = 200 EUR
    HSBC = 400 HKD
    Equity:Opening

This work fine as long as I only check the files individually.  But I also like to be able to consider several years in the same query.  For this I made a file "main.dat" that just contains a list of include directives for all the other files:

include 2013.dat
include 2014.dat
include 2015.dat

But this does not work, because then ledger complains about the "zero balanced transaction".  The problem can be seen with this simple file:

2015-07-01 Test
    HSBC        10 HKD
    Incomes

2015-07-02 Adjust
    HSBC    = 10 HKD
    Incomes

Resulting in the "null amount" error.  Every time I got this it takes me some time to figure out what's going on.  After all when I only look at the error line, I don't see any null amount.  When I change any transaction value before the adjustment, it then mysteriously work.

Maybe my way of putting an adjustment transaction at the top of each year is bad practice?  But in that case how is the correct way to do it?

Regards,
Guillaume

Lifepillar

unread,
Sep 8, 2015, 4:10:44 AM9/8/15
to ledge...@googlegroups.com
On 2015-09-08 07:27:47 +0000, Guillaume Chéreau said:

> Maybe my way of putting an adjustment transaction at the top of each
> year is bad practice?  But in that case how is the correct way to do it?

Below I explain how I do it (pasting from one of the commits in my repo).
The TLDR is that you generate an equity report at the end of each year.

"Keep a folder for each year. Each folder is completely independent,
and contains the files for a single year. Then, there is a main.ledger
file in the top folder, which is the file that is normally used in ledger
commands. So, the overall structure is as follows:

./main.ledger
./2014/journal.ledger
./2014/equity.ledger
./2014/accounts.ledger
./2014/payees.ledger
./2014/tags.ledger
./2014/budget.ledger
./2014/...
./2015/journal.ledger
./2015/equity.ledger
./2015/accounts.ledger
./2015/payees.ledger
./2015/tags.ledger
./2015/budget.ledger
./2015/...

The content of main.ledger is just:

; -*- ledger -*-
include 2015/journal.ledger

That is, main.ledger includes the latest journal (of course, this
must be updated once a year).

2015/journal.ledger starts as follows:

; To make this folder completely self-contained, comment out
; the first include below and uncomment the second one.
include ../2014/journal.ledger
;include equity.ledger

; Include this year's additional files
include accounts.ledger
include budget.ledger
...

That is, each YYYY/journal.ledger starts by including the previous
year's journal.

An important file is equity.ledger. To get the equity report for
a given year (say, 2015), use:

ledger -f 2014/journal.ledger --effective -y '%Y/%m/%d' equity
>2015/equity.ledger

Note that you get the equity for a given year from the journal
of the previous year. The --effective option is necessary if
there are transactions across different years (e.g., with actual
date '2014/12/31' and effective date '2015/1/1'), otherwise the
balances won't match, for example, your bank statement.

To archive or throw away files, say, before 2010, just open
2011/journal.ledger and replace the include of the previous year's
ledger with the include of equity.ledger (see above). You might
have to add the accounts appearing in equity.ledger to the current
accounts."

A last important note: it is imperative that you *never* use the same
account in both real and virtual transactions, otherwise you will get
an error upon trying to generate an equity report. This has been
previously discussed in this list, but I don't recall the title of the
thread(s).

Enjoy,
Life


Reply all
Reply to author
Forward
0 new messages