For some time, I used org-mode to generate invoices for clients. This setup used a set of hacky elisp functions, some yasnippet snippets and some rough LaTeX hacks.
This project cleans up that setup into something more refined and robust. I do not plan to create an ELPA package or contribute it to org-mode, but others may find it useful. The approach is simple and it works well for my needs. Your results may differ.
- Generate a PDF invoice based on tasks completed since the last invoice.
- Support a Sales/VAT/GST type tax, including a configurable rate and tax name.
- Include work expenses on the invoice, for example expenses you paid to do the work and now pass on to the client.
- Set a different hourly rate and payment terms for each client.
- Re-generate invoices as required.
Each client file needs 6 headings: Client, Tasks, Notes, Expenses, Invoices, and Clock. See Usage for details on each heading. You can add other sections to the client file, but these 6 are required.
You can use a yasnippet template to generate new client files and set up the initial configuration, though yasnippet is optional and not required to use this package.
To generate a new invoice, run the command oi-make-new-invoice (M-x
oi-make-new-invoice) from within the client file. This command finds
clocked work done since the last invoice and creates a new invoice with
the new data. The generated invoice contains a services section.
This section summarises up to 3 levels of tasks, adds the times, and
multiplies the total time by the client's charge rate to get a total. The
invoicing process can add a tax, such as VAT or GST, based on a rate set
in the Invoices property section. This tax amount is added to the total
to get a final charge. The process then adds any expenses not yet
submitted, in a new Expenses section on the invoice, to reach the final
amount due.
At this stage, the easiest way to install this module is to clone the git repository and add the src directory to your load-path variable. Alternatively, put the org-invoicing.el file in a directory already in your load-path. You can then load it with (require 'org-invoicing).
Besides the oi-invoice.el file, the repository also has a LaTeX class file called invoicing.sty, in the latex directory. Place this file somewhere on your system, then set the oi-invoice-style variable to point to it.
This package needs Emacs 30.1 or later and Org 9.7 or later.
After you load the file, run M-x customize-group org-invoicing to set up a few things. In particular, customise these variables:
- oi-company: a plist of details about your company or consultancy, for example name, address, phone number, and email address.
- oi-invoice-style: a path to the invoice.sty file. Do not include the .sty extension. Use the full path to the file.
This is an opinionated library. It does not offer the same level of customisation as the rest of org, unless you edit the elisp code. One area that must follow a specific format is the client org file. The library expects specific tables, properties, and headlines to exist. You can add extra headings and tables, but the core layout below must stay in place. A basic example follows.
#+TITLE: ACME Widgets Ltd
#+LATEX_HEADER: \usepackage{tabularx}
* Client
#+NAME: Client
#+BEGIN table
| Name | Acme Widgets Pty Ltd |
| Address 1 | 99 Factory Rd. |
| Address 2 | Industrious, DEVISTATE 9999 |
| Address 3 | |
| Rate | 20.00 |
| Tax | 0.10 |
| Tax Name | GST |
| Terms | 14 |
#+END:
* Tasks
* Notes
* Expenses
* Invoices
:PROPERTIES:
:INVOICE_PREFIX: A
:LAST_INV_NO: 1
:PERIOD_START: <2020-11-11 Wed 17:48>
:END:
* Clock
The client file drives the system. Use a separate client file for each
client. At a minimum, each client file needs these headings: Client, Tasks, Notes, Expenses, Invoices and Clock. You can add other headlines,
but these 6 must exist.
- For each client, use a client org file that lists all tasks for that client. These tasks are basic TODO items.
- Each client file has a Client heading. This heading holds a table with the client's contact information, such as address, phone number, and contact emails.
- Each client file has a Tasks section. This section holds the TODOS for the client. A capture template exists for this section, though the default org-mode template also works.
- Each client file has an Expenses section. This section records expenses you pay and then pass on to the client, such as travel or accommodation costs. An Expenses capture template captures key details about each expense, including links to supporting documents such as receipts, which you may need to include in the expense submission. Each expense stores its date, description, and amount in a table. Each expense sits in its own level-2 heading under the main Expenses heading.
- Each client file has an Invoices section, where the system tracks invoices. This section holds a property drawer with details such as the charge rate, the last invoice number used for automatic numbering, and the period covered by the last invoice. Inside this section, each invoice has its own sub-section with summary details: the invoice period, expenses added to the invoice, hours or items on the invoice, and a link to the PDF file for the invoice.
To run the test suite:
emacs -batch -l ert -l src/org-invoicing.el -l test/org-invoicing-test.el -f ert-run-tests-batch-and-exit
README.md is generated from this file. After you edit README.org, regenerate README.md with:
emacs --batch -l bin/build-readme.el
GPLv3 License.
Copyright 2020-2026 Tim Cross