Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for re-write rules (aka ledger "views", allows keeping separate books) (BZ#714) #714

Open
tbm opened this issue Mar 17, 2012 · 5 comments
Labels
enhancement New feature or request P3 Average priority

Comments

@tbm
Copy link
Contributor

tbm commented Mar 17, 2012

Note: the issue was created automatically with bugzilla2github

Bugzilla bug ID: BZ#714
From: Martin Michlmayr (@tbm)
CC: @blais, @thdox

@tbm
Copy link
Contributor Author

tbm commented Mar 17, 2012

Comment author: Martin Michlmayr (@tbm)

I'd like to propose a feature (for post 3.0) that would make ledger
even more powerful and useful. It would make it easier to keep
separate books (e.g. cash vs accrual) and to get useful information
out of ledger.

My idea is inspired by SQL views. In SQL, you can can define a
view which is essential a query that makes data available in a
virtual table that can be queried normally. (This idea is unrelated
to ledger's recently SQL support, though, afaict.)

Essentially what I'd like to do is to specify a config file in
ledger that would tell ledger how to re-write certain transactions
before showing them to me.

Let's consider some examples of how this would be useful.

Example 1) Cash vs accruals basis

I have Google ads on my web site and get a small income from this.
In ledger, I account for this income as it accrues (on a monthly
basis): every month, I login and check how much I've earned this
month and then I add this ledger. But I only get paid from Google
when I reach 70 EUR or so (in the example I use 0.02 EUR).

So in ledger I have transactions like this:

2012-01-31 * AdSense earnings (1 Jan - 31 Jan)
    Assets:Receivable:AdSense                            0.01 EUR
    Income:AdSense

2012-02-29 * AdSense earnings (1 Feb - 29 Feb)
    Assets:Receivable:AdSense                            0.02 EUR
    Income:AdSense

2012-03-01 * AdSense payment
    Assets:Bank                                           0.02 EUR
    Assets:Receivable:AdSense                            -0.02 EUR

So far so good. The problem is that when I do my tax return, I don't
have to specify income I've accrued but only money that has been paid
to me. So I have to ignore the Assets:Receivable:AdSense entries and
only look for actual payments to my bank account. Essentially, I have
to convert my accruals based accounting system to cash based accounting.

It would be great if I could tell ledger in a config file:

  • ignore all transactions that involve Assets:Receivable:AdSense
    and Income:AdSense
  • and re-write all transactions that involve Assets:Receivable:AdSense
    and Assets:Bank and re-write Assets:Receivable:AdSense to
    Income:AdSense in this case.

In the example above, this would delete the first two transactions
and leave me with the following transaction:

2012-03-01 * AdSense payment
    Assets:Bank                                           0.02 EUR
    Income:AdSense                                       -0.02 EUR

(Bonus points if I can also re-write the description from "AdSense
payment" to "AdSense earnings".)

Example 2) Combining accounts into one - salary, taxes, etc

A lot of us are tracking our personal finance. We sometimes get
the question as to how to track salary best: should we track all
gross income and then track deductions, such as tax. Or should we
simply enter our net pay since this is the figure we typically care
about.

This question was recently asked on this list and I argued in
http://www.mail-archive.com/ledger-cli@ googlegroups.com/msg02552.html
that the correct way is to account for the gross income plus all
deductions. However, this makes it hard to see the net pay since
you have to specify all deductions, e.g.:
bal income:employment:salary expenses:tax:income expenses:tax:ni

This is another example that could be simplified if ledger would
allow to specify a config file to re-write transactions. I could
then track all information (gross income, tax paid, social security,
etc), but I could also specify a config file that would simply it
for me.

Let's take a simpler example: let's say you receive money from PayPal.
PayPal takes a fee so what you receive is actually less. So you have
something like this:

2012-02-07 * PayPal payment
    Income                                               -5.00 EUR
    Expenses:Fees:PayPal                                  0.57 EUR
    Assets:PayPal                                         4.43 EUR

In this case, if I want to know the net income, I have to run:

$ ledger -f c.ledger bal incom expenses:
            0.57 EUR  Expenses:Fees:PayPal
           -5.00 EUR  Income
--------------------
           -4.43 EUR

What I'd like to do is specify a file containing re-write rules so
that this transaction would become:

2012-02-07 * PayPal payment
    Income                                               -4.43 EUR
    Assets:PayPal                                         4.43 EUR

Then I could run ledger reg on my ledger file and get:

2012-02-07 PayPal payment  Income               -5.00 EUR -5.00 EUR
                           Expenses:Fees:PayPal  0.57 EUR -4.43 EUR
                           Assets:PayPal         4.43 EUR         0

But if I'd specify ledger reg --re-write test, I'd get:

2012-02-07 PayPal payment  Income           -4.43 EUR    -4.43 EUR
                           Assets:PayPal     4.43 EUR            0

I think such a feature would be very powerful and I can think of many
use cases for such a feature. John, how difficult would this be to
implement and does this fit into your plans for ledger?

@tbm
Copy link
Contributor Author

tbm commented Mar 17, 2012

Comment author: John Wiegley (@jwiegley)

This sounds like a fantastic feature for 3.1, and I think it fits beautifully.

One query you can do right now is this one:

  • ignore all transactions that involve Assets:Receivable:AdSense
    and Income:AdSense

This would be phrased as:

ledger reg -l 'expr ! (account =~ /Receivable:AdSense/ && any(account =~ /Income:AdSense/)'

The 'any' operator is used to query whether any of the other postings -- in the transaction of a matched posting -- match an expression.

But I see that your idea goes much beyond this, to allow reconfiguring transactions, adding and dropping postings, adding and dropping transactions, etc. I think something automated transactions can be extended to do this by adding an expression based rewriter, rather than the simplistic postings-manipulator that it currently provides.

@tbm
Copy link
Contributor Author

tbm commented Apr 22, 2014

Comment author: Martin Blais (@blais)

A few comments on this ticket:

First, Assets:Receivable:AdSense is not really a "receivable." You
actually have an account at Google with a balance in it; you should
probably track it as such. Anyway, that's just a nit about naming, but
let's call this Assets:Google:AdSense in what follows.

Second, you could potentially track it by having two separate
income accounts, and matching the amounts when you do have a
payment.

  2012-01-31 * "AdSense earnings (1 Jan - 31 Jan)"
      Assets:Google:AdSense                            0.01 EUR
      Income:AdSense:Accrual

  2012-02-29 * AdSense earnings (1 Feb - 29 Feb)
      Assets:Google:AdSense                            0.02 EUR
      Income:AdSense:Accrual

  2012-03-01 * AdSense payment
      Assets:Bank                                       0.03 EUR
      Assets:Google:AdSense                            -0.03 EUR
      Income:AdSense:Accrual                            0.03 EUR
      Income:AdSense                                   -0.03 EUR

I'll admit that it's inelegant to have to duplicate the transactions,
and that could use some automation, but you could do this now to work
around it and track income on a cash basis.

Thirdly, about the salary transaction, you cannot realistically
automate this. In practice, those transactions nearly always have
little variations that make it impossible to specify a pattern...
sometime even a difference of one cent on a deduction between
otherwise identical paychecks (possibly due to rounding), or expenses
paid back, etc. You really do have to enter them one by one based off
of your pay stubs, it's not accurate otherwise. I don't think it's
possible to do so on paychecks.

@tbm
Copy link
Contributor Author

tbm commented May 21, 2014

Comment author: Martin Michlmayr (@tbm)

(In reply to comment #2)

First, Assets:Receivable:AdSense is not really a "receivable." You
actually have an account at Google with a balance in it; you should
probably track it as such. Anyway, that's just a nit about naming, but
let's call this Assets:Google:AdSense in what follows.

This is an interesting observation, but after thinking about it I think I disagree with you. Even though I can see my "account balance" with Google at any time, I cannot access the money. I have to wait for Google to transfer the money to me and they only do it once I reach a certain amount. As such, this is more like a receivable. If Google went out of business, I would not receive my money and would have to write off my receivable.

This is different to e.g. a PayPal account where I can request payment at any time.

Second, you could potentially track it by having two separate
income accounts, and matching the amounts when you do have a
payment.

2012-01-31 * "AdSense earnings (1 Jan - 31 Jan)"
Assets:Google:AdSense 0.01 EUR
Income:AdSense:Accrual

2012-02-29 * AdSense earnings (1 Feb - 29 Feb)
Assets:Google:AdSense 0.02 EUR
Income:AdSense:Accrual

2012-03-01 * AdSense payment
Assets:Bank 0.03 EUR
Assets:Google:AdSense -0.03 EUR
Income:AdSense:Accrual 0.03 EUR
Income:AdSense -0.03 EUR

I'll admit that it's inelegant to have to duplicate the transactions,
and that could use some automation, but you could do this now to work
around it and track income on a cash basis.

I agree that this achieves what I'm looking for but I also agree that it's inelegant.

Thirdly, about the salary transaction, you cannot realistically
automate this. In practice, those transactions nearly always have
little variations that make it impossible to specify a pattern...

The amounts may vary, but the accounts stay the same.

Basically, I just want to be able to specify queries that transform the ledger data. How complicated the queries are are up to me...

Before this feature is implemented, it probably makes sense to think about some specific use cases.

@tbm
Copy link
Contributor Author

tbm commented May 24, 2014

Comment author: Martin Blais (@blais)

(In reply to comment #3)

(In reply to comment #2)

First, Assets:Receivable:AdSense is not really a "receivable." You
actually have an account at Google with a balance in it; you should
probably track it as such. Anyway, that's just a nit about naming, but
let's call this Assets:Google:AdSense in what follows.

This is an interesting observation, but after thinking about it I think I
disagree with you. Even though I can see my "account balance" with Google
at any time, I cannot access the money. I have to wait for Google to
transfer the money to me and they only do it once I reach a certain amount.
As such, this is more like a receivable. If Google went out of business, I
would not receive my money and would have to write off my receivable.

This is different to e.g. a PayPal account where I can request payment at
any time.

If PayPal went out of business, you would not receive your money and would have to write off the account.

If you billed Google Inc. - an opaque entity which hasn't paid you yet - with an invoice for contract work done, that would be a clear receivable IMO, because you are the one tracking the amounts being owed. But this AdSense account has your name all over it, you can even "log in to your account" and see the accrued balance and they're tracking for you. It looks and feels to me much more like a bank account than an amount not received from "another" entity, even if it has restrictions on it. Note that you also can't just get your money from a bank, there's a process, going to the counter, accessing an ATM, etc. - try initiating an outgoing wire transfer without being present in the bank's country, for example, and see how well that goes (basically impossible with most banks, and yup, that's your money you cannot get).

It is a small semantic difference, and I'm not sure what unambiguous criteria would define a receivable. I'm not sure there even is a definitive answer. What makes sense to me, is that the factor that decides it is whether you are the one tracking them to pay you or whether there is a remote account with your name on it that takes care of that in your name. Even then that's not decisive, I'm sure you can come up with a counterexample.

Second, you could potentially track it by having two separate
income accounts, and matching the amounts when you do have a
payment.

2012-01-31 * "AdSense earnings (1 Jan - 31 Jan)"
Assets:Google:AdSense 0.01 EUR
Income:AdSense:Accrual

2012-02-29 * AdSense earnings (1 Feb - 29 Feb)
Assets:Google:AdSense 0.02 EUR
Income:AdSense:Accrual

2012-03-01 * AdSense payment
Assets:Bank 0.03 EUR
Assets:Google:AdSense -0.03 EUR
Income:AdSense:Accrual 0.03 EUR
Income:AdSense -0.03 EUR

I'll admit that it's inelegant to have to duplicate the transactions,
and that could use some automation, but you could do this now to work
around it and track income on a cash basis.

I agree that this achieves what I'm looking for but I also agree that it's
inelegant.

I really do think solving the problem of cash vs. accrual accounting more generally is an important one and should have a well-known solution for it. We ought to have a long discussion about just that topic sometime.

Maybe it's time for the first worldwide Ledger conference :-)

@tbm tbm added P3 Average priority enhancement New feature or request labels May 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request P3 Average priority
Projects
None yet
Development

No branches or pull requests

1 participant