Skip to content
Dmitry Astapov edited this page Mar 16, 2024 · 3 revisions

Associated directory: 13-tax-returns

Managing expectations

Hledger will not file a tax return for you, but it could aid you in filing one.

Hopefully, your financial records contain enough information to compute some (or maybe all) the figures you need for your tax return. It is just a matter of producing the right report.

Since I am familiar with the UK tax system, I will use it as an example for the rest of this section. In the UK, the fiscal year ends on 5th of April, and shortly after all employees are issued with "form P60", which itemizes their earnings and deductions for the last fiscal year. You will have to report these on your tax return. If you had other income -- for example, in the form of interest -- you will have to report it as well.

For simplicity, I am going to limit myself to this extremely short and incomplete model. In this section, we would create a report that crosses a calendar year boundary to encompass the fiscal year, deals with income from employment and bank interest, incorporates data received on the imaginary end-of-year P60 form, and presents all of this information in the form that would help you file your tax return.

Recording inputs

Our journal files already contain some earnings and interest transactions and I am adding more in this example directory, so that every month in 2016-2017 would have a payment transaction from the Employer Inc.

We now have to find a way to represent information from the P60. Let's imagine that for the tax year 2016-2017 this form says that gross income was £26789, of which £2681.27 have been deducted as income tax, and £1184.02 deducted as National Insurance contributions.

We would love to check this information against our record, as the payroll department is only human, and could've made mistakes.

How can we record this information, though? It is not a financial transaction that we have made, we have no suitable accounts to balance these figures against. However, what we can do is to record them as virtual postings, that don't obey double-entry accounting rules and don't have to balance. We could create a new transaction at the end of the fiscal year and record all the information from the P60 in it:

$ hledger -f 2017.journal print p60

2017-04-05 2016/2017 Tax return, P60
    (p60:gross pay)                   £26789
    (p60:tax paid)                 £-2681.27
    (p60:national insurance)       £-1184.02

Computing outputs

We would now be able to automate the checking of the P60 figures against our financial records. If we tally up our income transactions for the fiscal year, they should add up to exactly (GROSS - TAX - NATIONAL INSURANCE) numbers, as shown on P60. And we could verify it using hledger if we ask for the balance report that includes just our income transactions and numbers from P60:

$ hledger -f all.journal balance p60 income:employer -b 2016-04-06 -e 2017-04-06

          £-22923.71  income:employer
           £26789.00  p60:gross pay
           £-1184.02  p60:national insurance
           £-2681.27  p60:tax paid
--------------------
                   0  

If the balance is not zero, someone had made a mistake - either we or the payroll department. As an additional safeguard you can record individual payslips as virtual postings, and then hledger register will allow you to quickly pinpoint the month in which the discrepancy occurred -- all the correct months will have your real income transactions being perfectly offset with virtual payslip postings, but the month where discrepancy occurs will not have its balance (as reported by register) go back exactly to zero.

What else can we do? We could include a total of all non-employment income in our report, we could itemize it via hledger register. We can use the virtual posting trick to add any other financial statements we receive -- such as pension fund reports, for example -- and have them checked against our records. For now, given our limited journals, we could just include the "gross interest" figure in our report

$ cat export/2016-2017-tax.txt

INCOME TOTALS
=============
              £-1.21  income:interest
--------------------
              £-1.21  

PAYSLIPS CHECK
==============
          £-22923.71  income:employer
           £22923.71  p60
           £26789.00    gross pay
           £-1184.02    national insurance
           £-2681.27    tax paid
--------------------
                   0  

As this report will live under version control, you would be immediately alerted if any changes in your journal files cause the figures that went into your tax return to change.

Scripting it

The general idea is easy, and by now should be familiar: let's make a script that accepts two years that contain the fiscal year we are interested in, and generates all the figures that we need.

We only need to feed the correct input files to hledger invocations in that script: we can't use all.journal as it could contain references to the files that are not yet generated during this run of the export.sh. So we must write build rules in export.hs to ensure that <this year>.journal and <previous year>.journal are fully generated, and use just them.

Just like we do in all.journal, we need to process both yearly files and the "end-of-year" file that comes between them. We can generate a small file that includes all the inputs we need and feed it to the hledger. All of this could be seen in the script called tax_return.sh that you would find in 13-tax-returns or diffs/12-to-13.diff.

Next steps

To be continued!