Beancount importer for Paychex payroll data
Find a file
2025-02-20 14:26:45 +11:00
bin Extend build docs to describe dependencies 2025-02-20 14:26:45 +11:00
resources Add example data and test, fix ungrouping, extend docs 2024-02-22 14:06:45 +11:00
src Apply cljfmt 2025-02-10 12:53:33 +11:00
test Apply cljfmt 2025-02-10 12:53:33 +11:00
.dir-locals.el Document and tidy 2024-02-22 11:07:59 +11:00
.gitignore Add a demo mode 2024-03-15 17:17:41 +11:00
build.clj Add a demo mode 2024-03-15 17:17:41 +11:00
deps.edn Add a demo mode 2024-03-15 17:17:41 +11:00
LICENSE.txt Document and tidy 2024-02-22 11:07:59 +11:00
manifest.scm Extend build docs to describe dependencies 2025-02-20 14:26:45 +11:00
README.md Extend build docs to describe dependencies 2025-02-20 14:26:45 +11:00
tests.edn Add tests.edn to avoid Kaocha warnings 2024-02-22 14:12:42 +11:00
TODO.md Extend build docs to describe dependencies 2025-02-20 14:26:45 +11:00

Paychex payroll importer for Beancount

This tool automates the monthly task of transcribing a payroll CSV from service provider Paychex into around 300 lines of fairly intricate Beancount bookkeeping data.

Usage

The run, the program requires a Java runtime (tested with OpenJDK 17 and 21). On Debian 12 (Bookworm):

sudo apt install openjdk-17-jre

Run a demo with two example employees, Jack and Jill Citizen:

java -jar import-x.x.x-standalone.jar --demo

Provide your own payroll data with:

java -jar import-x.x.x-standalone.jar --csv resources/example-paychex-pay-item-details.csv --total-fees 206.50

In the above, various values such as the date, time period covered and receipt/invoice values show "TODO" placeholders that you are expected to fill in later. If you prefer, you can provide any/all of these explicitly:

java -jar import-x.x.x-standalone.jar --csv resources/example-paychex-pay-item-details.csv --date 2023-12-29 --period 'December 2023' --total-fees 206.50 --pay-receipt-no rt:19462/674660 --pay-invoice-no rt:19403/675431 --fees-receipt-no rt:19459/675387 --fees-invoice-no rt:19459/674887 --retirement-receipt-no rt:19403/676724 --retirement-invoice-no rt:19403/675431

You can test the output in Beancount by adding the following header entries to define the accounts:

2023-01-01 open Assets:FR:Check2721
2023-01-01 open Assets:FR:Check1345
2023-01-01 open Expenses:Payroll:Salary
2023-01-01 open Expenses:Payroll:Fees
2023-01-01 open Expenses:Payroll:Tax
2023-01-01 open Expenses:Hosting
2023-01-01 open Expenses:Insurance
2023-01-01 open Liabilities:Payable:Accounts

Then run Beancount with:

bean-report [your file] balances

Building

To build you need a Java SDK (tested with OpenJDK 17 and 21) and Clojure. On Debian 12 (Bookworm):

sudo apt install openjdk-17-jdk clojure

To build, run:

bin/build

This will output a JAR file like target/import-x.x.x-standalone.jar, where the version number is based on the Git revision.

Development

Run tests with:

bin/test

You can run without building using:

bin/dev --csv resources/example-paychex-pay-item-details.csv --total-fees 206.50

The project is set up for development in Emacs and CIDER-mode. Open a source file and run cider-jack-in.

Why Clojure?

Clojure is very well-suited to this kind of data transformation/manipulation. Even without fully understanding the implications of all the accounting/tax concepts I was able to parse the previous human-generated Beancount entries into a data structure and work backwards to produce results that matched exactly, without worrying about exact text formatting. Libraries like deep-diff2 and the editor-integrated REPL made it very efficient to compare the data structures and build the program - certainly much more efficient than developing the same program in Python. It's only just over 500 lines of code and we've had zero bugs as of writing (one year since it was built).