Skip to content

Repository files navigation

LaTeX Invoice

A config once, inter-month-idempotent, calendar aware, capable and maintenance-free invoice solution written in LaTeX + Lua.

Features

  • Config once: Set your company, client and project information using ENV vars in the .envrc.secret file (git ignored). No LaTeX or Lua skills needed!
  • Inter-month-idempotent: You build the invoice any number of times, it always results in the same invoice number when run within the same month. The proceeding month the next invoice number will be used.
  • Calendar aware: Using your machines system time to determine the month, it calculates the number of working days for the target month. Invoice date is set to last day of the target month and due date is set dependent on the payment terms set in your ENV config.
  • Capable: Supports setting number of days you were off, to be extracted from the automatically calculated number of working days. Supports expenses using "',,';',,'" CSV inspired string.
  • Maintenance free: The invoice number automatically set based on the current month. When you build the invoice the next month, the next number is used.

Requirements

With minimal modification this ought to work on Linux too, but I've only verified it on macOS.

direnv

Install direnv

brew install direnv

Direnv allows your system to automatically to load the environment variables standing in this projects.

LaTeX

There are two different ways of installing LaTeX on macOS. Either install MacTeX which is a complete and very big distribution, which will eat up ~10 gb of your space. Use that if you have all that space to spare and want the easiest installation. Alternatively you can install TinyTex which is a much (typically 90%) smaller distribution. I recommend TinyTex since it is small and fast and it only has one extra required installation step which is fast and easy.

TinyTex

Install LaTeX (TinyTex) here

curl -sL "https://yihui.org/tinytex/install-bin-unix.sh" | sh

You will be prompted for your password.

A package manager called tlmgr is now installed, we will use it in the next section to install some packages.

Install LaTeX Packages

Install the following packages:

tlmgr install babel-english fancyhdr arydshln lastpage datetime2 fp ragged2e xstring fancybox luacode threeparttable

LaTeX should now be setup!

Uninstalling MacTex

If you have previously installed MacTex and want to switch over to TinyTex, uninstall MacTex like so:

Remove MacTeX package files

Run this command in Terminal to remove the main MacTeX installation (typically 4-9 GB):

sudo rm -rf /usr/local/texlive

Remove the TeX Live utility symlinks

These links point to the binaries inside the MacTeX install.

sudo rm -rf /Library/TeX

You may also want to remove any profile entries from:

sudo rm /etc/paths.d/TeX

Remove GUI apps installed by MacTeX

These may include:

  • TeX Live Utility (/Applications/TeX)
  • TeXShop (/Applications/TeXShop.app)

You can delete them manually from the /Applications folder.

Setup

Clone this repo, then cd to it.

Create .envrc.secret

Make copy of .envrc.example and call it .envrc.secret

cp .envrc.example .envrc.secret

Replace the placeholder values from .envrc.example with your company, client and project values.

Source and make

Source the updated environment variables by calling:

direnv allow .

And now call make:

make

Which will call out to lualatex.

Usage

Note

All environment variables references to in document are all set in .envrc.secret (which you should have copied over from .envrc.example). They will all be exported when you call direnv allow . (needed once and then after each change to .envrc.secret, which you typically only upon initial setup)

Build the invoice (make standing in the root of this project) on the first day month after the completed month. So if you have finished working in May, wait until June and build it. The invoice date will be set to 2025-05-31 and the due date will be set to invoice day + $INVOICE_DAYS_DUE_AFTER_END_OF_MONTH.

Set INVOICE_NUMBER_BASE_OFFSET = 42 if you have sent 42 invoices already and want the next to invoice to be 43, in order for this to work you need also set INVOICE_NUMBER_BASE_OFFSET_DATE_MONTH and INVOICE_NUMBER_BASE_OFFSET_DATE_YEAR to the previous month (and relevant year).

Note

The invoice will be named "<INVOICEMONTH>_invoice<INVOICE_NUMBER>.pdf" and places in a folder next to the makefile called invoices. This name is inter-month-idempotent, running several times same month will use same name. Next month the next invoice will be generated with the subsequent month using the subsequent invoice number.

Did not invoice at all for some month?

If you were out of office (OOO) for an entire month, maybe due to parental leave or long vacation or long term sickness, you can set increment INVOICE_NUMBER_MONTHS_FREE by how many numbers of months you where OOO. This allows you to not have to "hacky" decrement your INVOICE_NUMBER_BASE_OFFSET to get the correct invoice number for the next month.

Out of office for some days?

If you were out of office for some days for the period you are invoicing you can call:

make DAYS_OFF=5

Expenses?

make EXPENSES="'Sandwich,8.67,1';'Coffee,4.20,2'"

Or if you had days of and expenses:

make DAYS_OFF=2 EXPENSES="'Headphones,79.99,1'"

Which will subtract 5 from the number of working days that month (as calculated by the Lua script for you).

Example

If you build the invoice without changing any of the example values from .envrc.example, built with make DAYS_OFF=3 EXPENSES="'Sandwich,8.67,1';'Coffee,4.20,2'" it will look like this:

Example

How it works

direnv will source .envrc which in turn will source .envrc.example and then if .envrc.secret exists, it will source that, effectively overriding the values of .envrc.example. If you haven't created .envrc.secret yet the values of .envrc.example are used instead, or if you were to comment out or remove any variable from .envrc.secret, that variable won't be overridden.

The LaTeX main file invoice.tex will include other helper files, such as logic.tex which in turn wraps the lua functions inside logic.lua as LaTeX commands.

Contribute

We use pre-commit to run some soundness checks when you try to commit, such as checking for typos.

Precommit

Install pre-commit CLI tool:

brew install pre-commit

Install pre-commit hooks

pre-commit install

About

Pretty, maintenance-free and ENV-configured Invoicing in LaTeX + Lua.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages