Invoice Generator
I’m a freelancer, and, as such, I have to be able to provide invoices to my clients (right now I don’t have any, but this is another issue).
Until now I was using the Upwork platform and a spreadsheet to generate invoices. In the future, I will have to use specialized software that provides these invoices to the government, complying with certain specifications that might change (and will require someone to specifically maintain it).
Anyway, I wanted to experiment with how to generate a PDF (invoice or not) in Go, so I started to look into it.
First I found an already-made tool called payment-recipt-generator, but I couldn’t get it to work (maybe I didn’t try too hard).
Then I found a library called gopdf, which I’ll talk about later.
After that, I found what seems to be the most advanced software for PDF generation, called unidoc, but it was proprietary software and I couldn’t afford it.
Then I found a toolset called pdfcpu, but it is for manipulating PDF files (like signing or encrypting a PDF), not generating them from scratch.
Next, I tried fpdf, which is a translation of a PHP library of the same name, but it generates PDF documents in version 1.3 (when PDFs were controlled by Adobe). Just for this reason alone, it’s not worth it.
In the end, I also found an interesting tool called invoice, but I decided not to use it.
Another option I considered was to generate an HTML file and convert it to PDF using gotenberg or wkhtmltopdf, but that would be my last resort.
So, in the end, I decided to use the library gopdf. I learned how to create a PDF using this library thanks to its examples. I also learned how fonts work in PDF files and took a lot of time to choose one (actually two: a regular one and a bold one). Then I learned how to add a background and draw lines and shapes.
For the metadata information, I decided to take the easy way, so I downloaded a command-line tool with:
sudo apt install libimage-exiftool-perl
And I edited the information myself. To remember the exact command to use and have some consistency, I decided to print to the console the exact command and parameters, as well as how to check the results. This is how the output for the default invoice looks:
Remember to execute these commands:
exiftool -Title="Default Invoice" -Author="[Your Name Here]" -Creator="genFact v0.9.7" -Producer="signintech/gopdf" -overwrite_original output/default.pdf
pdfinfo output/default.pdf
Once the metadata is handled, let’s move on to how I did the rest. I wanted to have it in two parts: One file always stays the same, containing my information, client information (which would always be Upwork), and other static text. The other file contains variable information like the date, applied taxes, and every line on the invoice.
So I first started coding everything in raw form, just to see how it would look. Then I changed every value into a global variable. For example, for creating a line from point A (x=10, y=30) to B (x=100, y=30), instead of having something like this:
pdf.Line(10, 30, 100, 30)
I would have something like this:
Ax, Ay := 10, 30
Bx, By := 100, 30
pdf.Line(Ax, Ay, Bx, By)
So, changing these variables would change the outcome.
Finally, I decided to have some default values for these variables and read two files with data to overwrite them. These two files correspond to the fixed and variable information I mentioned earlier. At first I thought of using JSON, but finally I decided to use a TSV (Tab-Separated Values) and a .DAT (abbreviation of Data) that was just a regular text file with a variable = data structure.
In the end I ended up with a single huge 1,335-line file. But it works as expected. You can check it on my GitHub.