Notes to self

Invoicing from the command line

Are you a freelancer? You don’t need to leave your command line to create invoices for your clients. InvoicePrinter is a Ruby library for producing PDF invoices without too much hassle. If you haven’t seen it before, you can read more about it in the announcement or its GitHub page. With the upcoming 1.1.0 release (currently as release candidate) a command line executable is included so you can now use command line to invoice your clients. No need to learn Ruby, just pass the data in the familiar JSON format! Here is how to create your first invoices.

Installation

InvoicePrinter requires Ruby. If you are on Fedora or Fedora-based systems just run:

$ sudo dnf install ruby

And then install the pre-release of the gem via RubyGems (we need 1.1.0.rc1 or higher):

$ gem install invoice_printer --pre

Now the executable called invoice_printer should be available on your path.

Creating the first invoice

$ invoice_printer --document '{}' --filename out.pdf

Now opening out.pdf will give you a familiar structure of an invoice. But something is missing. Data!

As I suggested in the beginning we need to provide InvoicePrinter with a JSON representing our data. Here is one that is not empty:

{
   "number":"NO. 198900000001",
   "provider_name":"John White",
   "provider_tax_id":"",
   "provider_tax_id2":"",
   "provider_street":"5th Avenue",
   "provider_street_number":"1",
   "provider_postcode":"747 05",
   "provider_city":"NYC",
   "provider_city_part":"",
   "provider_extra_address_line":"",
   "purchaser_name":"Will Black",
   "purchaser_tax_id":"",
   "purchaser_tax_id2":"",
   "purchaser_street":"7th Avenue",
   "purchaser_street_number":"1",
   "purchaser_postcode":"747 70",
   "purchaser_city":"NYC",
   "purchaser_city_part":"",
   "purchaser_extra_address_line":"",
   "issue_date":"05/03/2016",
   "due_date":"19/03/2016",
   "subtotal":"$ 1,000",
   "tax":"$ 100",
   "tax2":"",
   "tax3":"",
   "total":"$ 1,100",
   "bank_account_number":"156546546465",
   "account_iban":"",
   "account_swift":"",
   "items":[
      {
         "name":"Programming",
         "quantity":"10",
         "unit":"hr",
         "price":"$ 60",
         "tax":"$ 60",
         "tax2":"",
         "tax3":"",
         "amount":"$ 600"
      },
      {
         "name":"Consulting",
         "quantity":"10",
         "unit":"hr",
         "price":"$ 30",
         "tax":"$ 30",
         "tax2":"",
         "tax3":"",
         "amount":"$ 300"
      },
      {
         "name":"Support",
         "quantity":"20",
         "unit":"hr",
         "price":"$ 15",
         "tax":"$ 30",
         "tax2":"",
         "tax3":"",
         "amount":"$ 330"
      }
   ],
   "note":"This is a note at the end."
}

The command changes to:

$ invoice_printer --document '{"number":"NO. 198900000001","provider_name":"John White","provider_tax_id":"","provider_tax_id2":"","provider_street":"5th Avenue","provider_street_number":"1","provider_postcode":"747 05","provider_city":"NYC","provider_city_part":"","provider_extra_address_line":"","purchaser_name":"Will Black","purchaser_tax_id":"","purchaser_tax_id2":"","purchaser_street":"7th Avenue","purchaser_street_number":"1","purchaser_postcode":"747 70","purchaser_city":"NYC","purchaser_city_part":"","purchaser_extra_address_line":"","issue_date":"05/03/2016","due_date":"19/03/2016","subtotal":"$ 1,000","tax":"$ 100","tax2":"","tax3":"","total":"$ 1,100","bank_account_number":"156546546465","account_iban":"","account_swift":"","items":[{"name":"Programming","quantity":"10","unit":"hr","price":"$ 60","tax":"$ 60","tax2":"","tax3":"","amount":"$ 600"},{"name":"Consulting","quantity":"10","unit":"hr","price":"$ 30","tax":"$ 30","tax2":"","tax3":"","amount":"$ 300"},{"name":"Support","quantity":"20","unit":"hr","price":"$ 15","tax":"$ 30","tax2":"","tax3":"","amount":"$ 330"}],"note":"This is a note at the end."}' --filename out.pdf

out.pdf is your first real invoice, so congratulations!

Editing labels

We fixed our empty invoice with data but what if we don’t like our predefined labels? There is a --labels switch we can take advantage of and provide our own in JSON. The following command would translate the labels into Czech:

$ invoice_printer --labels '{"name":"Faktura","provider":"Prodejce","purchaser":"Kupující","tax_id":"IČ","tax_id2":"DIČ","payment":"Forma úhrady","payment_by_transfer":"Platba na následující účet:","account_number":"Číslo účtu","issue_date":"Datum vydání","due_date":"Datum splatnosti","item":"Položka","quantity":"Počet","unit":"MJ","price_per_item":"Cena za položku","amount":"Celkem bez daně","subtotal":"Cena bez daně","tax":"DPH 21 %","total":"Celkem"}' --document '{"number":"NO. 198900000001","provider_name":"John White","provider_tax_id":"","provider_tax_id2":"","provider_street":"5th Avenue","provider_street_number":"1","provider_postcode":"747 05","provider_city":"NYC","provider_city_part":"","provider_extra_address_line":"","purchaser_name":"Will Black","purchaser_tax_id":"","purchaser_tax_id2":"","purchaser_street":"7th Avenue","purchaser_street_number":"1","purchaser_postcode":"747 70","purchaser_city":"NYC","purchaser_city_part":"","purchaser_extra_address_line":"","issue_date":"05/03/2016","due_date":"19/03/2016","subtotal":"$ 1,000","tax":"$ 100","tax2":"","tax3":"","total":"$ 1,100","bank_account_number":"156546546465","account_iban":"","account_swift":"","items":[{"name":"Programming","quantity":"10","unit":"hr","price":"$ 60","tax":"$ 60","tax2":"","tax3":"","amount":"$ 600"},{"name":"Consulting","quantity":"10","unit":"hr","price":"$ 30","tax":"$ 30","tax2":"","tax3":"","amount":"$ 300"},{"name":"Support","quantity":"20","unit":"hr","price":"$ 15","tax":"$ 30","tax2":"","tax3":"","amount":"$ 330"}],"note":"This is a note at the end."}' --font examples/Overpass-Regular.ttf --filename out.pdf

For clarity this is the JSON used:

{
   "name":"Faktura",
   "provider":"Prodejce",
   "purchaser":"Kupující",
   "tax_id":"IČ",
   "tax_id2":"DIČ",
   "payment":"Forma úhrady",
   "payment_by_transfer":"Platba na následující účet:",
   "account_number":"Číslo účtu",
   "issue_date":"Datum vydání",
   "due_date":"Datum splatnosti",
   "item":"Položka",
   "quantity":"Počet",
   "unit":"MJ",
   "price_per_item":"Cena za položku",
   "amount":"Celkem bez daně",
   "subtotal":"Cena bez daně",
   "tax":"DPH 21 %",
   "total":"Celkem"
}

Changing the default font

Attentive readers noticed that I used an extra --font switch in the last example. This is to change to default font to something that would support my language of choice (Czech in this case).

$ invoice_printer --document '{}' --font examples/Overpass-Regular.ttf --filename out.pdf

Including company logo

If you are a serious business you probably include a logotype on your invoices. InvoicePrinter supports logotypes with --logo switch so the only thing you need to do is to provide a path to the image itself as follows:

$ invoice_printer --document '{}' --logo examples/logo.png --filename out.pdf

Remember you can always run invoice_printer --help if you don’t remember a particular switch. And remember that InvoicePrinter is an actual Ruby library you can include in your programs, just go and read README.

Happy hacking and invoicing!

Check out my book
Deployment from Scratch is unique Linux book about web application deployment. Learn how deployment works from the first principles rather than YAML files of a specific tool.
by Josef Strzibny
RSS